From 45e781d42c9759f63a28e239f2301ce5a4c98987 Mon Sep 17 00:00:00 2001 From: Ebere Abanonu Date: Thu, 31 Mar 2022 16:18:12 +0100 Subject: [PATCH 1/2] Port `Akka.Tests.Pattern` tests to `async/await` - `BackoffSupervisorSpec` --- .../Pattern/BackoffSupervisorSpec.cs | 207 +++++++++--------- 1 file changed, 104 insertions(+), 103 deletions(-) diff --git a/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs b/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs index 961ce85403c..6846b65ae60 100644 --- a/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs +++ b/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs @@ -9,6 +9,7 @@ using System.Collections; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using Akka.Actor; using Akka.Pattern; using Akka.TestKit; @@ -91,55 +92,55 @@ public static Props Props(IActorRef probe) #endregion [Fact(Skip = "Racy on Azure DevOps")] - public void BackoffSupervisor_must_start_child_again_when_it_stops_when_using_Backoff_OnStop() + public async Task BackoffSupervisor_must_start_child_again_when_it_stops_when_using_Backoff_OnStop() { var supervisor = Create(OnStopOptions()); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); c1.Tell(PoisonPill.Instance); - ExpectTerminated(c1); - AwaitAssert(() => + await ExpectTerminatedAsync(c1); + await AwaitAssertAsync(async() => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); // new instance - ExpectMsg().Ref.Should().NotBeSameAs(c1); + (await ExpectMsgAsync()).Ref.Should().NotBeSameAs(c1); }); } [Fact] - public void BackoffSupervisor_must_forward_messages_to_the_child() + public async Task BackoffSupervisor_must_forward_messages_to_the_child() { - Action assertForward = supervisor => + Func assertForward = async supervisor => { supervisor.Tell("hello"); - ExpectMsg("hello"); + await ExpectMsgAsync("hello"); }; - assertForward(Create(OnStopOptions())); - assertForward(Create(OnFailureOptions())); + await assertForward(Create(OnStopOptions())); + await assertForward(Create(OnFailureOptions())); } [Fact] - public void BackoffSupervisor_must_support_custom_supervision_strategy() + public async Task BackoffSupervisor_must_support_custom_supervision_strategy() { - Action assertCustomStrategy = supervisor => + Func assertCustomStrategy = async supervisor => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); c1.Tell("boom"); - ExpectTerminated(c1); - AwaitAssert(() => + await ExpectTerminatedAsync(c1); + await AwaitAssertAsync(async () => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); // new instance - ExpectMsg().Ref.Should().NotBeSameAs(c1); + (await ExpectMsgAsync()).Ref.Should().NotBeSameAs(c1); }); }; // TODO: use FilterException - EventFilter.Exception().Expect(2, () => + await EventFilter.Exception().ExpectAsync(2, async () => { var stoppingStrategy = new OneForOneStrategy(ex => { @@ -161,77 +162,77 @@ public void BackoffSupervisor_must_support_custom_supervision_strategy() return Directive.Escalate; }); - assertCustomStrategy(Create(OnStopOptions().WithSupervisorStrategy(stoppingStrategy))); - assertCustomStrategy(Create(OnFailureOptions().WithSupervisorStrategy(restartingStrategy))); + await assertCustomStrategy(Create(OnStopOptions().WithSupervisorStrategy(stoppingStrategy))); + await assertCustomStrategy(Create(OnFailureOptions().WithSupervisorStrategy(restartingStrategy))); }); } [Fact] - public void BackoffSupervisor_must_support_default_stopping_strategy_when_using_Backoff_OnStop() + public async Task BackoffSupervisor_must_support_default_stopping_strategy_when_using_Backoff_OnStop() { // TODO: use FilterException - EventFilter.Exception().Expect(1, () => + await EventFilter.Exception().ExpectAsync(1, async () => { var supervisor = Create(OnStopOptions().WithDefaultStoppingStrategy().WithManualReset()); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(0); + (await ExpectMsgAsync()).Count.Should().Be(0); c1.Tell("boom"); - ExpectTerminated(c1); - AwaitAssert(() => + await ExpectTerminatedAsync(c1); + await AwaitAssertAsync(async() => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); // new instance - ExpectMsg().Ref.Should().NotBeSameAs(c1); + (await ExpectMsgAsync()).Ref.Should().NotBeSameAs(c1); }); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(1); + (await ExpectMsgAsync()).Count.Should().Be(1); }); } [Fact] - public void BackoffSupervisor_must_support_manual_reset() + public async Task BackoffSupervisor_must_support_manual_reset() { - Action assertManualReset = supervisor => + Func assertManualReset = async supervisor => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); c1.Tell("boom"); - ExpectTerminated(c1); + await ExpectTerminatedAsync(c1); - AwaitAssert(() => + await AwaitAssertAsync(async() => { supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(1); + (await ExpectMsgAsync()).Count.Should().Be(1); }); - AwaitAssert(() => + await AwaitAssertAsync(async () => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); // new instance - ExpectMsg().Ref.Should().NotBeSameAs(c1); + (await ExpectMsgAsync()).Ref.Should().NotBeSameAs(c1); }); // TODO: this Thread.Sleep should be removed - Thread.Sleep(500); + await Task.Delay(500); supervisor.Tell("hello"); - ExpectMsg("hello"); + await ExpectMsgAsync("hello"); // making sure the Reset is handled by supervisor supervisor.Tell("hello"); - ExpectMsg("hello"); + await ExpectMsgAsync("hello"); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(0); + (await ExpectMsgAsync()).Count.Should().Be(0); }; // TODO: use FilterException - EventFilter.Exception().Expect(2, () => + await EventFilter.Exception().ExpectAsync(2, async() => { var stoppingStrategy = new OneForOneStrategy(ex => { @@ -255,12 +256,12 @@ public void BackoffSupervisor_must_support_manual_reset() return Directive.Restart; }); - assertManualReset( + await assertManualReset( Create(OnStopOptions(ManualChild.Props(TestActor)) .WithManualReset() .WithSupervisorStrategy(stoppingStrategy))); - assertManualReset( + await assertManualReset( Create(OnFailureOptions(ManualChild.Props(TestActor)) .WithManualReset() .WithSupervisorStrategy(restartingStrategy))); @@ -268,57 +269,57 @@ public void BackoffSupervisor_must_support_manual_reset() } [Fact] - public void BackoffSupervisor_must_reply_to_sender_if_replyWhileStopped_is_specified() + public async Task BackoffSupervisor_must_reply_to_sender_if_replyWhileStopped_is_specified() { - EventFilter.Exception().Expect(1, () => + await EventFilter.Exception().ExpectAsync(1, async() => { var supervisor = Create(Backoff.OnFailure(Child.Props(TestActor), "c1", TimeSpan.FromSeconds(100), TimeSpan.FromSeconds(300), 0.2, -1) .WithReplyWhileStopped("child was stopped")); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(0); + (await ExpectMsgAsync()).Count.Should().Be(0); c1.Tell("boom"); - ExpectTerminated(c1); + await ExpectTerminatedAsync(c1); - AwaitAssert(() => + await AwaitAssertAsync(async() => { supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(1); + (await ExpectMsgAsync()).Count.Should().Be(1); }); supervisor.Tell("boom"); - ExpectMsg("child was stopped"); + await ExpectMsgAsync("child was stopped"); }); } [Fact] - public void BackoffSupervisor_must_not_reply_to_sender_if_replyWhileStopped_is_not_specified() + public async Task BackoffSupervisor_must_not_reply_to_sender_if_replyWhileStopped_is_not_specified() { - EventFilter.Exception().Expect(1, () => + await EventFilter.Exception().ExpectAsync(1, async() => { var supervisor = Create(Backoff.OnFailure(Child.Props(TestActor), "c1", TimeSpan.FromSeconds(100), TimeSpan.FromSeconds(300), 0.2, -1)); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(0); + (await ExpectMsgAsync()).Count.Should().Be(0); c1.Tell("boom"); - ExpectTerminated(c1); + await ExpectTerminatedAsync(c1); - AwaitAssert(() => + await AwaitAssertAsync(async() => { supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(1); + (await ExpectMsgAsync()).Count.Should().Be(1); }); supervisor.Tell("boom"); //this will be sent to deadLetters - ExpectNoMsg(500); + await ExpectNoMsgAsync(500); }); } @@ -346,142 +347,142 @@ internal class DelayTable : IEnumerable } [Fact(Skip = "Racy on Azure DevOps")] - public void BackoffSupervisor_must_stop_restarting_the_child_after_reaching_maxNrOfRetries_limit_using_BackOff_OnStop() + public async Task BackoffSupervisor_must_stop_restarting_the_child_after_reaching_maxNrOfRetries_limit_using_BackOff_OnStop() { var supervisor = Create(OnStopOptions(maxNrOfRetries: 2)); - IActorRef WaitForChild() + async Task WaitForChild() { - AwaitCondition(() => + await AwaitConditionAsync(async() => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c = ExpectMsg().Ref; + var c = (await ExpectMsgAsync()).Ref; return !c.IsNobody(); }, TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(50)); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - return ExpectMsg().Ref; + return (await ExpectMsgAsync()).Ref; } Watch(supervisor); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(0); + (await ExpectMsgAsync()).Count.Should().Be(0); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); c1.Tell(PoisonPill.Instance); - ExpectTerminated(c1); + await ExpectTerminatedAsync(c1); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(1); + (await ExpectMsgAsync()).Count.Should().Be(1); - var c2 = WaitForChild(); - AwaitAssert(() => c2.ShouldNotBe(c1)); + var c2 = await WaitForChild(); + await AwaitAssertAsync(() => c2.ShouldNotBe(c1)); Watch(c2); c2.Tell(PoisonPill.Instance); - ExpectTerminated(c2); + await ExpectTerminatedAsync(c2); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(2); + (await ExpectMsgAsync()).Count.Should().Be(2); - var c3 = WaitForChild(); - AwaitAssert(() => c3.ShouldNotBe(c2)); + var c3 = await WaitForChild(); + await AwaitAssertAsync(() => c3.ShouldNotBe(c2)); Watch(c3); c3.Tell(PoisonPill.Instance); - ExpectTerminated(c3); - ExpectTerminated(supervisor); + await ExpectTerminatedAsync(c3); + await ExpectTerminatedAsync(supervisor); } [Fact(Skip = "Racy on Azure DevOps")] - public void BackoffSupervisor_must_stop_restarting_the_child_after_reaching_maxNrOfRetries_limit_using_BackOff_OnFailure() + public async Task BackoffSupervisor_must_stop_restarting_the_child_after_reaching_maxNrOfRetries_limit_using_BackOff_OnFailure() { - EventFilter.Exception().Expect(3, () => + await EventFilter.Exception().ExpectAsync(3, async() => { var supervisor = Create(OnFailureOptions(maxNrOfRetries: 2)); - IActorRef WaitForChild() + async Task WaitForChild() { - AwaitCondition(() => + await AwaitConditionAsync(async () => { supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c = ExpectMsg().Ref; + var c = (await ExpectMsgAsync()).Ref; return !c.IsNobody(); }, TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(50)); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - return ExpectMsg().Ref; + return (await ExpectMsgAsync()).Ref; } Watch(supervisor); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(0); + (await ExpectMsgAsync()).Count.Should().Be(0); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); c1.Tell("boom"); - ExpectTerminated(c1); + await ExpectTerminatedAsync(c1); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(1); + (await ExpectMsgAsync()).Count.Should().Be(1); - var c2 = WaitForChild(); - AwaitAssert(() => c2.ShouldNotBe(c1)); + var c2 = await WaitForChild(); + await AwaitAssertAsync(() => c2.ShouldNotBe(c1)); Watch(c2); c2.Tell("boom"); - ExpectTerminated(c2); + await ExpectTerminatedAsync(c2); supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); - ExpectMsg().Count.Should().Be(2); + (await ExpectMsgAsync()).Count.Should().Be(2); - var c3 = WaitForChild(); - AwaitAssert(() => c3.ShouldNotBe(c2)); + var c3 = await WaitForChild(); + await AwaitAssertAsync(() => c3.ShouldNotBe(c2)); Watch(c3); c3.Tell("boom"); - ExpectTerminated(c3); - ExpectTerminated(supervisor); + await ExpectTerminatedAsync(c3); + await ExpectTerminatedAsync(supervisor); }); } [Fact] - public void BackoffSupervisor_must_stop_restarting_the_child_if_final_stop_message_received_using_BackOff_OnStop() + public async Task BackoffSupervisor_must_stop_restarting_the_child_if_final_stop_message_received_using_BackOff_OnStop() { const string stopMessage = "stop"; var supervisor = Create(OnStopOptions(maxNrOfRetries: 100).WithFinalStopMessage(message => ReferenceEquals(message, stopMessage))); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; var parentSupervisor = CreateTestProbe(); Watch(c1); parentSupervisor.Watch(supervisor); supervisor.Tell(stopMessage); - ExpectMsg("stop"); + await ExpectMsgAsync("stop"); c1.Tell(PoisonPill.Instance); - ExpectTerminated(c1); - parentSupervisor.ExpectTerminated(supervisor); + await ExpectTerminatedAsync(c1); + await parentSupervisor.ExpectTerminatedAsync(supervisor); } [Fact] - public void BackoffSupervisor_must_not_stop_when_final_stop_message_has_not_been_received() + public async Task BackoffSupervisor_must_not_stop_when_final_stop_message_has_not_been_received() { const string stopMessage = "stop"; var supervisorWatcher = new TestProbe(Sys, new XunitAssertions()); var supervisor = Create(OnStopOptions(maxNrOfRetries: 100).WithFinalStopMessage(message => ReferenceEquals(message, stopMessage))); supervisor.Tell(BackoffSupervisor.GetCurrentChild.Instance); - var c1 = ExpectMsg().Ref; + var c1 = (await ExpectMsgAsync()).Ref; Watch(c1); supervisorWatcher.Watch(supervisor); c1.Tell(PoisonPill.Instance); - ExpectTerminated(c1); + await ExpectTerminatedAsync(c1); supervisor.Tell("ping"); - supervisorWatcher.ExpectNoMsg(TimeSpan.FromMilliseconds(20)); // supervisor must not terminate + await supervisorWatcher.ExpectNoMsgAsync(TimeSpan.FromMilliseconds(20)); // supervisor must not terminate supervisor.Tell(stopMessage); - supervisorWatcher.ExpectTerminated(supervisor); + await supervisorWatcher.ExpectTerminatedAsync(supervisor); } } } From f2dc76d25c442ffff83f80d08818c67719db8e2b Mon Sep 17 00:00:00 2001 From: Gregorius Soedharmo Date: Fri, 1 Apr 2022 03:06:02 +0700 Subject: [PATCH 2/2] Mark possible racy source --- src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs b/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs index 6846b65ae60..8d51fd25bb3 100644 --- a/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs +++ b/src/core/Akka.Tests/Pattern/BackoffSupervisorSpec.cs @@ -378,6 +378,7 @@ await AwaitConditionAsync(async() => supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); (await ExpectMsgAsync()).Count.Should().Be(1); + // This code looks suspicious, this might be the cause of the raciness var c2 = await WaitForChild(); await AwaitAssertAsync(() => c2.ShouldNotBe(c1)); Watch(c2); @@ -429,6 +430,7 @@ await AwaitConditionAsync(async () => supervisor.Tell(BackoffSupervisor.GetRestartCount.Instance); (await ExpectMsgAsync()).Count.Should().Be(1); + // This code looks suspicious, this might be the cause of the raciness var c2 = await WaitForChild(); await AwaitAssertAsync(() => c2.ShouldNotBe(c1)); Watch(c2);