diff --git a/GFramework.Core.Tests/coroutine/CoroutineExtensionsTests.cs b/GFramework.Core.Tests/coroutine/CoroutineExtensionsTests.cs
new file mode 100644
index 0000000..2d1f3e4
--- /dev/null
+++ b/GFramework.Core.Tests/coroutine/CoroutineExtensionsTests.cs
@@ -0,0 +1,564 @@
+using GFramework.Core.Abstractions.coroutine;
+using GFramework.Core.coroutine;
+using GFramework.Core.coroutine.extensions;
+using GFramework.Core.coroutine.instructions;
+using NUnit.Framework;
+
+namespace GFramework.Core.Tests.coroutine;
+
+///
+/// 协程扩展方法的单元测试类
+/// 测试内容包括:
+/// - RepeatEvery方法
+/// - ExecuteAfter方法
+/// - Sequence方法
+/// - ParallelCoroutines方法
+/// - WaitForSecondsWithProgress方法
+///
+[TestFixture]
+public class CoroutineExtensionsTests
+{
+ ///
+ /// 验证RepeatEvery应该返回有效的协程
+ ///
+ [Test]
+ public void RepeatEvery_Should_Return_Valid_Coroutine()
+ {
+ var callCount = 0;
+ var coroutine = CoroutineExtensions.RepeatEvery(0.1, () => callCount++, 3);
+
+ Assert.That(coroutine, Is.InstanceOf>());
+ }
+
+ ///
+ /// 验证RepeatEvery应该执行指定次数
+ ///
+ [Test]
+ public void RepeatEvery_Should_Execute_Specified_Times()
+ {
+ var callCount = 0;
+ var coroutine = CoroutineExtensions.RepeatEvery(0.1, () => callCount++, 3);
+
+ while (coroutine.MoveNext())
+ {
+ coroutine.Current.Update(0.1);
+ }
+
+ Assert.That(callCount, Is.EqualTo(3));
+ }
+
+ ///
+ /// 验证RepeatEvery应该无限执行当count为null
+ ///
+ [Test]
+ public void RepeatEvery_Should_Execute_Forever_When_Count_Is_Null()
+ {
+ var callCount = 0;
+ var coroutine = CoroutineExtensions.RepeatEvery(0.1, () => callCount++);
+
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(coroutine.MoveNext(), Is.True);
+ coroutine.Current.Update(0.1);
+ }
+
+ Assert.That(callCount, Is.EqualTo(5));
+ Assert.That(coroutine.MoveNext(), Is.True);
+ }
+
+ ///
+ /// 验证RepeatEvery应该处理负数count
+ ///
+ [Test]
+ public void RepeatEvery_Should_Handle_Negative_Count()
+ {
+ var callCount = 0;
+ var coroutine = CoroutineExtensions.RepeatEvery(0.1, () => callCount++, -1);
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(callCount, Is.EqualTo(0));
+ }
+
+ ///
+ /// 验证RepeatEvery应该处理零count
+ ///
+ [Test]
+ public void RepeatEvery_Should_Handle_Zero_Count()
+ {
+ var callCount = 0;
+ var coroutine = CoroutineExtensions.RepeatEvery(0.1, () => callCount++, 0);
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(callCount, Is.EqualTo(0));
+ }
+
+ ///
+ /// 验证RepeatEvery应该处理null action
+ ///
+ [Test]
+ public void RepeatEvery_Should_Handle_Null_Action()
+ {
+ var coroutine = CoroutineExtensions.RepeatEvery(0.1, null, 3);
+
+ Assert.DoesNotThrow(() =>
+ {
+ while (coroutine.MoveNext())
+ {
+ coroutine.Current.Update(0.1);
+ }
+ });
+ }
+
+ ///
+ /// 验证ExecuteAfter应该返回有效的协程
+ ///
+ [Test]
+ public void ExecuteAfter_Should_Return_Valid_Coroutine()
+ {
+ var called = false;
+ var coroutine = CoroutineExtensions.ExecuteAfter(1.0, () => called = true);
+
+ Assert.That(coroutine, Is.InstanceOf>());
+ }
+
+ ///
+ /// 验证ExecuteAfter应该在延迟后执行action
+ ///
+ [Test]
+ public void ExecuteAfter_Should_Execute_Action_After_Delay()
+ {
+ var called = false;
+ var coroutine = CoroutineExtensions.ExecuteAfter(1.0, () => called = true);
+
+ Assert.That(called, Is.False);
+
+ coroutine.MoveNext();
+ coroutine.Current.Update(0.5);
+ Assert.That(called, Is.False);
+
+ coroutine.Current.Update(0.5);
+ Assert.That(called, Is.False);
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(called, Is.True);
+ }
+
+ ///
+ /// 验证ExecuteAfter应该处理零延迟
+ ///
+ [Test]
+ public void ExecuteAfter_Should_Handle_Zero_Delay()
+ {
+ var called = false;
+ var coroutine = CoroutineExtensions.ExecuteAfter(0, () => called = true);
+
+ coroutine.MoveNext();
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(called, Is.True);
+ }
+
+ ///
+ /// 验证ExecuteAfter应该处理负数延迟
+ ///
+ [Test]
+ public void ExecuteAfter_Should_Handle_Negative_Delay()
+ {
+ var called = false;
+ var coroutine = CoroutineExtensions.ExecuteAfter(-1.0, () => called = true);
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(called, Is.False);
+ }
+
+ ///
+ /// 验证ExecuteAfter应该处理null action
+ ///
+ [Test]
+ public void ExecuteAfter_Should_Handle_Null_Action()
+ {
+ var coroutine = CoroutineExtensions.ExecuteAfter(1.0, null);
+
+ Assert.DoesNotThrow(() =>
+ {
+ coroutine.MoveNext();
+ coroutine.Current.Update(1.0);
+ });
+ }
+
+ ///
+ /// 验证Sequence应该返回有效的协程
+ ///
+ [Test]
+ public void Sequence_Should_Return_Valid_Coroutine()
+ {
+ var coroutine1 = CreateSimpleCoroutine();
+ var coroutine2 = CreateSimpleCoroutine();
+ var sequence = CoroutineExtensions.Sequence(coroutine1, coroutine2);
+
+ Assert.That(sequence, Is.InstanceOf>());
+ }
+
+ ///
+ /// 验证Sequence应该按顺序执行多个协程
+ ///
+ [Test]
+ public void Sequence_Should_Execute_Coroutines_In_Order()
+ {
+ var executionOrder = new List();
+ var coroutine1 = CreateCoroutineWithCallback(1, () => executionOrder.Add(1));
+ var coroutine2 = CreateCoroutineWithCallback(2, () => executionOrder.Add(2));
+ var coroutine3 = CreateCoroutineWithCallback(3, () => executionOrder.Add(3));
+
+ var sequence = CoroutineExtensions.Sequence(coroutine1, coroutine2, coroutine3);
+
+ while (sequence.MoveNext())
+ {
+ sequence.Current.Update(0.1);
+ }
+
+ Assert.That(executionOrder, Is.EqualTo(new List { 1, 2, 3 }));
+ }
+
+ ///
+ /// 验证Sequence应该处理空协程数组
+ ///
+ [Test]
+ public void Sequence_Should_Handle_Empty_Coroutines()
+ {
+ var sequence = CoroutineExtensions.Sequence();
+
+ Assert.That(sequence.MoveNext(), Is.False);
+ }
+
+ ///
+ /// 验证Sequence应该处理单个协程
+ ///
+ [Test]
+ public void Sequence_Should_Handle_Single_Coroutine()
+ {
+ var coroutine1 = CreateSimpleCoroutine();
+ var sequence = CoroutineExtensions.Sequence(coroutine1);
+
+ Assert.That(sequence.MoveNext(), Is.False);
+ }
+
+ ///
+ /// 验证Sequence应该处理null协程
+ ///
+ [Test]
+ public void Sequence_Should_Handle_Null_Coroutine()
+ {
+ var coroutine1 = CreateSimpleCoroutine();
+ var sequence = CoroutineExtensions.Sequence(coroutine1, null!);
+
+ Assert.Throws(() =>
+ {
+ while (sequence.MoveNext())
+ {
+ sequence.Current.Update(0.1);
+ }
+ });
+ }
+
+ ///
+ /// 验证ParallelCoroutines应该返回有效的协程
+ ///
+ [Test]
+ public void ParallelCoroutines_Should_Return_Valid_Coroutine()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var coroutine1 = CreateSimpleCoroutine();
+ var coroutine2 = CreateSimpleCoroutine();
+
+ var parallel = scheduler.ParallelCoroutines(coroutine1, coroutine2);
+
+ Assert.That(parallel, Is.InstanceOf>());
+ }
+
+ ///
+ /// 验证ParallelCoroutines应该并行执行多个协程
+ ///
+ [Test]
+ public void ParallelCoroutines_Should_Execute_Coroutines_In_Parallel()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var executionCounts = new Dictionary { { 1, 0 }, { 2, 0 }, { 3, 0 } };
+ var coroutine1 = CreateDelayedCoroutine(() => executionCounts[1]++, 0.5);
+ var coroutine2 = CreateDelayedCoroutine(() => executionCounts[2]++, 0.5);
+ var coroutine3 = CreateDelayedCoroutine(() => executionCounts[3]++, 0.5);
+
+ var parallel = scheduler.ParallelCoroutines(coroutine1, coroutine2, coroutine3);
+
+ parallel.MoveNext();
+
+ Assert.That(scheduler.ActiveCoroutineCount, Is.GreaterThan(0));
+
+ while (scheduler.ActiveCoroutineCount > 0)
+ {
+ scheduler.Update();
+ }
+
+ Assert.That(executionCounts[1], Is.EqualTo(1));
+ Assert.That(executionCounts[2], Is.EqualTo(1));
+ Assert.That(executionCounts[3], Is.EqualTo(1));
+ }
+
+ ///
+ /// 验证ParallelCoroutines应该处理空数组
+ ///
+ [Test]
+ public void ParallelCoroutines_Should_Handle_Empty_Array()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var parallel = scheduler.ParallelCoroutines();
+
+ Assert.That(parallel.MoveNext(), Is.False);
+ }
+
+ ///
+ /// 验证ParallelCoroutines应该处理null数组
+ ///
+ [Test]
+ public void ParallelCoroutines_Should_Handle_Null_Array()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var parallel = scheduler.ParallelCoroutines(null);
+
+ Assert.That(parallel.MoveNext(), Is.False);
+ }
+
+ ///
+ /// 验证WaitForSecondsWithProgress应该返回有效的协程
+ ///
+ [Test]
+ public void WaitForSecondsWithProgress_Should_Return_Valid_Coroutine()
+ {
+ var progressValues = new List();
+ var coroutine = CoroutineExtensions.WaitForSecondsWithProgress(1.0, progressValues.Add);
+
+ Assert.That(coroutine, Is.InstanceOf>());
+ }
+
+ ///
+ /// 验证WaitForSecondsWithProgress应该在指定时间后完成
+ ///
+ [Test]
+ public void WaitForSecondsWithProgress_Should_Complete_After_Duration()
+ {
+ var coroutine = CoroutineExtensions.WaitForSecondsWithProgress(1.0, null);
+
+ coroutine.MoveNext();
+ coroutine.Current.Update(0.5);
+ Assert.That(coroutine.Current.IsDone, Is.False);
+
+ coroutine.Current.Update(0.5);
+ Assert.That(coroutine.Current.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForSecondsWithProgress应该调用进度回调
+ ///
+ [Test]
+ public void WaitForSecondsWithProgress_Should_Call_Progress_Callback()
+ {
+ var progressValues = new List();
+ var coroutine = CoroutineExtensions.WaitForSecondsWithProgress(1.0, progressValues.Add);
+
+ coroutine.MoveNext();
+
+ while (!coroutine.Current.IsDone)
+ {
+ coroutine.Current.Update(0.1);
+ }
+
+ Assert.That(progressValues.Count, Is.GreaterThan(0));
+ Assert.That(progressValues[0], Is.EqualTo(0.0f).Within(0.01f));
+ Assert.That(progressValues[^1], Is.EqualTo(1.0f).Within(0.01f));
+ }
+
+ ///
+ /// 验证WaitForSecondsWithProgress应该处理零时间
+ ///
+ [Test]
+ public void WaitForSecondsWithProgress_Should_Handle_Zero_Duration()
+ {
+ var progressValues = new List();
+ var coroutine = CoroutineExtensions.WaitForSecondsWithProgress(0, progressValues.Add);
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(progressValues, Is.EqualTo(new List { 1.0f }));
+ }
+
+ ///
+ /// 验证WaitForSecondsWithProgress应该处理负数时间
+ ///
+ [Test]
+ public void WaitForSecondsWithProgress_Should_Handle_Negative_Duration()
+ {
+ var progressValues = new List();
+ var coroutine = CoroutineExtensions.WaitForSecondsWithProgress(-1.0, progressValues.Add);
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(progressValues, Is.EqualTo(new List { 1.0f }));
+ }
+
+ ///
+ /// 验证WaitForSecondsWithProgress应该处理null回调
+ ///
+ [Test]
+ public void WaitForSecondsWithProgress_Should_Handle_Null_Callback()
+ {
+ var coroutine = CoroutineExtensions.WaitForSecondsWithProgress(1.0, null);
+
+ coroutine.MoveNext();
+ coroutine.Current.Update(0.5);
+ Assert.That(coroutine.Current.IsDone, Is.False);
+
+ coroutine.Current.Update(0.5);
+ Assert.That(coroutine.Current.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证RepeatEvery应该使用Delay指令
+ ///
+ [Test]
+ public void RepeatEvery_Should_Use_Delay_Instruction()
+ {
+ var coroutine = CoroutineExtensions.RepeatEvery(0.5, () => { }, 1);
+
+ coroutine.MoveNext();
+ Assert.That(coroutine.Current, Is.InstanceOf());
+ }
+
+ ///
+ /// 验证ExecuteAfter应该使用Delay指令
+ ///
+ [Test]
+ public void ExecuteAfter_Should_Use_Delay_Instruction()
+ {
+ var coroutine = CoroutineExtensions.ExecuteAfter(1.0, () => { });
+
+ coroutine.MoveNext();
+ Assert.That(coroutine.Current, Is.InstanceOf());
+ }
+
+ ///
+ /// 验证Sequence应该清理已完成的协程
+ ///
+ [Test]
+ public void Sequence_Should_Dispose_Completed_Coroutines()
+ {
+ var coroutine1 = CreateSimpleCoroutine();
+ var coroutine2 = CreateSimpleCoroutine();
+
+ var sequence = CoroutineExtensions.Sequence(coroutine1, coroutine2);
+
+ while (sequence.MoveNext())
+ {
+ sequence.Current.Update(0.1);
+ }
+
+ Assert.That(sequence.MoveNext(), Is.False);
+ }
+
+ ///
+ /// 验证RepeatEvery的间隔时间
+ ///
+ [Test]
+ public void RepeatEvery_Should_Respect_Interval()
+ {
+ var callTimes = new List();
+ var coroutine = CoroutineExtensions.RepeatEvery(0.5, () => callTimes.Add(0), 3);
+
+ var currentTime = 0.0;
+ while (coroutine.MoveNext())
+ {
+ coroutine.Current.Update(0.5);
+ currentTime += 0.5;
+ }
+
+ Assert.That(callTimes.Count, Is.EqualTo(3));
+ }
+
+ ///
+ /// 验证ExecuteAfter的延迟时间
+ ///
+ [Test]
+ public void ExecuteAfter_Should_Respect_Delay()
+ {
+ var executed = false;
+ var currentTime = 0.0;
+ var coroutine = CoroutineExtensions.ExecuteAfter(1.5, () => executed = true);
+
+ coroutine.MoveNext();
+ coroutine.Current.Update(0.5);
+ currentTime += 0.5;
+ Assert.That(executed, Is.False);
+
+ coroutine.Current.Update(1.0);
+ currentTime += 1.0;
+ Assert.That(executed, Is.False);
+
+ Assert.That(coroutine.MoveNext(), Is.False);
+ Assert.That(executed, Is.True);
+ Assert.That(currentTime, Is.EqualTo(1.5));
+ }
+
+ ///
+ /// 创建简单的立即完成协程
+ ///
+ private IEnumerator CreateSimpleCoroutine()
+ {
+ yield break;
+ }
+
+ ///
+ /// 创建带回调的协程
+ ///
+ private IEnumerator CreateCoroutineWithCallback(int id, Action callback)
+ {
+ yield return new WaitOneFrame();
+ callback();
+ }
+
+ ///
+ /// 创建计数协程
+ ///
+ private IEnumerator CreateCountingCoroutine(int id, Action callback)
+ {
+ yield return new WaitOneFrame();
+ callback();
+ }
+
+ ///
+ /// 创建延迟协程
+ ///
+ private IEnumerator CreateDelayedCoroutine(Action callback, double delay)
+ {
+ yield return new Delay(delay);
+ callback();
+ }
+
+ ///
+ /// 测试用时间源类
+ ///
+ private class TestTimeSource : ITimeSource
+ {
+ public double CurrentTime { get; private set; }
+ public double DeltaTime { get; private set; }
+
+ public void Update()
+ {
+ DeltaTime = 0.016;
+ CurrentTime += DeltaTime;
+ }
+ }
+}
diff --git a/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs b/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs
new file mode 100644
index 0000000..6b94f05
--- /dev/null
+++ b/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs
@@ -0,0 +1,521 @@
+using GFramework.Core.Abstractions.coroutine;
+using GFramework.Core.coroutine;
+using GFramework.Core.coroutine.extensions;
+using GFramework.Core.coroutine.instructions;
+using NUnit.Framework;
+
+namespace GFramework.Core.Tests.coroutine;
+
+///
+/// WaitForAllCoroutines的单元测试类
+/// 测试内容包括:
+/// - 初始化和基本功能
+/// - IsDone属性行为
+/// - 空句柄集合处理
+/// - 单个协程处理
+/// - 多个协程处理
+/// - 与CoroutineScheduler集成
+///
+[TestFixture]
+public class WaitForAllCoroutinesTests
+{
+ ///
+ /// 验证WaitForAllCoroutines初始状态为未完成
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Not_Be_Done_Initially_With_Running_Coroutines()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var coroutine1 = CreateDelayedCoroutine(() => { }, 1.0);
+ var coroutine2 = CreateDelayedCoroutine(() => { }, 1.0);
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2)
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait.IsDone, Is.False);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该在所有协程完成后完成
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Be_Done_When_All_Coroutines_Complete()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var coroutine1 = CreateSimpleCoroutine();
+ var coroutine2 = CreateSimpleCoroutine();
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2)
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ scheduler.Update();
+ scheduler.Update();
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该在所有协程完成后完成(使用Delay)
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Wait_For_All_Delayed_Coroutines()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var executionCount = 0;
+ var coroutine1 = CreateDelayedCoroutine(() => executionCount++, 1.0);
+ var coroutine2 = CreateDelayedCoroutine(() => executionCount++, 1.0);
+ var coroutine3 = CreateDelayedCoroutine(() => executionCount++, 1.0);
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2),
+ scheduler.Run(coroutine3)
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait.IsDone, Is.False);
+ Assert.That(executionCount, Is.EqualTo(0));
+
+ for (var i = 0; i < 12; i++)
+ {
+ scheduler.Update();
+ }
+
+ Assert.That(wait.IsDone, Is.True);
+ Assert.That(executionCount, Is.EqualTo(3));
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理空句柄列表
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Empty_Handles_List()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var handles = Array.Empty();
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该抛出ArgumentNullException当handles为null
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Handles_Is_Null()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ Assert.Throws(() => new WaitForAllCoroutines(scheduler, null!));
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该抛出ArgumentNullException当scheduler为null
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Scheduler_Is_Null()
+ {
+ var handles = Array.Empty();
+
+ Assert.Throws(() => new WaitForAllCoroutines(null!, handles));
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理单个协程
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Single_Coroutine()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var coroutine = CreateSimpleCoroutine();
+
+ var handles = new List { scheduler.Run(coroutine) };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ scheduler.Update();
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该在部分协程完成时未完成
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Not_Be_Done_When_Some_Coroutines_Complete()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var executionCount = 0;
+ var coroutine1 = CreateSimpleCoroutine();
+ var coroutine2 = CreateDelayedCoroutine(() => executionCount++, 1.0);
+ var coroutine3 = CreateDelayedCoroutine(() => executionCount++, 1.0);
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2),
+ scheduler.Run(coroutine3)
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ scheduler.Update();
+
+ Assert.That(wait.IsDone, Is.False);
+ Assert.That(executionCount, Is.EqualTo(0));
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理被终止的协程
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Killed_Coroutines()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var coroutine1 = CreateDelayedCoroutine(() => { }, 1.0);
+ var coroutine2 = CreateDelayedCoroutine(() => { }, 1.0);
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2)
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait.IsDone, Is.False);
+
+ scheduler.Kill(handles[0]);
+
+ Assert.That(wait.IsDone, Is.False);
+
+ scheduler.Kill(handles[1]);
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理被暂停和恢复的协程
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Paused_And_Resumed_Coroutines()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var executionCount = 0;
+ var coroutine1 = CreateDelayedCoroutine(() => executionCount++, 1.0);
+ var coroutine2 = CreateDelayedCoroutine(() => executionCount++, 1.0);
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2)
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ scheduler.Pause(handles[0]);
+
+ for (var i = 0; i < 12; i++)
+ {
+ scheduler.Update();
+ }
+
+ Assert.That(wait.IsDone, Is.False);
+ Assert.That(executionCount, Is.EqualTo(1));
+
+ scheduler.Resume(handles[0]);
+
+ for (var i = 0; i < 12; i++)
+ {
+ scheduler.Update();
+ }
+
+ Assert.That(wait.IsDone, Is.True);
+ Assert.That(executionCount, Is.EqualTo(2));
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines的Update方法不影响状态
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Update_Should_Not_Affect_State()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var coroutine = CreateDelayedCoroutine(() => { }, 1.0);
+
+ var handles = new List { scheduler.Run(coroutine) };
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ wait.Update(0.1);
+ Assert.That(wait.IsDone, Is.False);
+
+ wait.Update(1.0);
+ Assert.That(wait.IsDone, Is.False);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理无效句柄
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Invalid_Handles()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var handles = new List { default };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理混合的有效和无效句柄
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Mixed_Valid_And_Invalid_Handles()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var coroutine = CreateSimpleCoroutine();
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine),
+ default
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ scheduler.Update();
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理大量协程
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Many_Coroutines()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var executionCount = 0;
+
+ var handles = new List();
+ for (var i = 0; i < 20; i++)
+ {
+ handles.Add(scheduler.Run(CreateDelayedCoroutine(() => executionCount++, 1.0)));
+ }
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait.IsDone, Is.False);
+
+ for (var i = 0; i < 120; i++)
+ {
+ scheduler.Update();
+ }
+
+ Assert.That(wait.IsDone, Is.True);
+ Assert.That(executionCount, Is.EqualTo(20));
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理抛出异常的协程
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Coroutines_With_Exceptions()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var coroutine1 = CreateSimpleCoroutine();
+ var coroutine2 = CreateExceptionCoroutine();
+ var coroutine3 = CreateSimpleCoroutine();
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2),
+ scheduler.Run(coroutine3)
+ };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ scheduler.Update();
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该与ParallelCoroutines扩展方法一起工作
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Work_With_ParallelCoroutines()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var executionOrder = new List();
+ var coroutine1 = CreateDelayedCoroutine(() => executionOrder.Add(1), 0.5);
+ var coroutine2 = CreateDelayedCoroutine(() => executionOrder.Add(2), 0.5);
+ var coroutine3 = CreateDelayedCoroutine(() => executionOrder.Add(3), 0.5);
+
+ var parallel = scheduler.ParallelCoroutines(coroutine1, coroutine2, coroutine3);
+
+ parallel.MoveNext();
+
+ while (scheduler.ActiveCoroutineCount > 0)
+ {
+ parallel.MoveNext();
+ scheduler.Update();
+ }
+
+ Assert.That(executionOrder.Count, Is.EqualTo(3));
+ Assert.That(executionOrder, Does.Contain(1));
+ Assert.That(executionOrder, Does.Contain(2));
+ Assert.That(executionOrder, Does.Contain(3));
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该实现IYieldInstruction接口
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Implement_IYieldInstruction()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var handles = Array.Empty();
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait, Is.InstanceOf());
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该在所有协程立即完成时立即完成
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Be_Done_Immediately_When_All_Coroutines_Complete_Immediately()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+
+ var coroutine1 = CreateSimpleCoroutine();
+ var coroutine2 = CreateSimpleCoroutine();
+
+ var handles = new List
+ {
+ scheduler.Run(coroutine1),
+ scheduler.Run(coroutine2)
+ };
+
+ scheduler.Update();
+ scheduler.Update();
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 验证WaitForAllCoroutines应该处理重复的句柄
+ ///
+ [Test]
+ public void WaitForAllCoroutines_Should_Handle_Duplicate_Handles()
+ {
+ var timeSource = new TestTimeSource();
+ var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
+ var coroutine = CreateDelayedCoroutine(() => { }, 1.0);
+
+ var handle = scheduler.Run(coroutine);
+ var handles = new List { handle, handle };
+
+ var wait = new WaitForAllCoroutines(scheduler, handles);
+
+ for (var i = 0; i < 12; i++)
+ {
+ scheduler.Update();
+ }
+
+ Assert.That(wait.IsDone, Is.True);
+ }
+
+ ///
+ /// 创建简单的立即完成协程
+ ///
+ private IEnumerator CreateSimpleCoroutine()
+ {
+ yield break;
+ }
+
+ ///
+ /// 创建带回调的协程
+ ///
+ private IEnumerator CreateCoroutineWithCallback(int id, Action callback)
+ {
+ yield return new WaitOneFrame();
+ callback();
+ }
+
+ ///
+ /// 创建延迟协程
+ ///
+ private IEnumerator CreateDelayedCoroutine(Action callback, double delay)
+ {
+ yield return new Delay(delay);
+ callback();
+ }
+
+ ///
+ /// 创建抛出异常的协程
+ ///
+ private IEnumerator CreateExceptionCoroutine()
+ {
+ yield return new WaitOneFrame();
+ throw new InvalidOperationException("Test exception");
+ }
+
+ ///
+ /// 测试用时间源类
+ ///
+ private class TestTimeSource : ITimeSource
+ {
+ public double CurrentTime { get; private set; }
+ public double DeltaTime { get; private set; }
+
+ public void Update()
+ {
+ DeltaTime = 0.1;
+ CurrentTime += DeltaTime;
+ }
+ }
+}