Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

harden racy ActorCellSpecs #6395

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions src/core/Akka.Tests/Actor/ActorCellSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,54 +22,55 @@ public class ActorCellSpec : AkkaSpec
{
public class DummyActor : ReceiveActor
{
public DummyActor(AutoResetEvent autoResetEvent)
public DummyActor()
{
ReceiveAny(m => autoResetEvent.Set());
ReceiveAny(m => Sender.Tell(m));
}
}

public class DummyAsyncActor : ReceiveActor
{
public DummyAsyncActor(AutoResetEvent autoResetEvent)
public DummyAsyncActor()
{
ReceiveAsync<string>(async m =>
{
await Task.Delay(500);
autoResetEvent.Set();
await Task.Delay(5);
Sender.Tell(m);
});
}
}

[Fact]
public void Cell_should_clear_current_message_after_receive()
public async Task Cell_should_clear_current_message_after_receive()
{
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
var actor = Sys.ActorOf(Props.Create(() => new DummyActor(autoResetEvent)));
actor.Tell("hello");
//ensure the message was received
autoResetEvent.WaitOne();
var refCell = actor as ActorRefWithCell;
var cell = refCell.Underlying as ActorCell;
// arrange
var actor = Sys.ActorOf(Props.Create(() => new DummyActor()));

// act
await actor.Ask<string>("hello", RemainingOrDefault);

// assert
var refCell = (ActorRefWithCell)actor;
//wait while current message is not null (that is, receive is not yet completed/exited)
SpinWait.SpinUntil(() => cell.CurrentMessage == null, TimeSpan.FromSeconds(2));

cell.CurrentMessage.ShouldBe(null);
AwaitCondition(() => refCell.Underlying is ActorCell { CurrentMessage: null });
}

[Fact]
public void Cell_should_clear_current_message_after_async_receive()
public async Task Cell_should_clear_current_message_after_async_receive()
{
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
var actor = Sys.ActorOf(Props.Create(() => new DummyAsyncActor(autoResetEvent)));
actor.Tell("hello");
//ensure the message was received
Assert.True(autoResetEvent.WaitOne(TimeSpan.FromSeconds(3)), "Timed out while waiting for autoreset event");
var refCell = actor as ActorRefWithCell;
var cell = refCell.Underlying as ActorCell;
// arrange
var actor = Sys.ActorOf(Props.Create(() => new DummyAsyncActor()));

// act
await actor.Ask<string>("hello", RemainingOrDefault);

// assert

var refCell = (ActorRefWithCell)actor;
//wait while current message is not null (that is, receive is not yet completed/exited)
SpinWait.SpinUntil(() => cell.CurrentMessage == null, TimeSpan.FromSeconds(2));

cell.CurrentMessage.ShouldBe(null);
AwaitCondition(() => refCell.Underlying is ActorCell { CurrentMessage: null });
}
}
}