Skip to content

Commit

Permalink
Become and BecomeStacked for ReceivePersistentActor
Browse files Browse the repository at this point in the history
  • Loading branch information
Horusiath committed Nov 3, 2015
1 parent dce684d commit b11dafc
Show file tree
Hide file tree
Showing 6 changed files with 536 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/core/Akka.Persistence.Tests/Akka.Persistence.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
<Compile Include="PersistentViewSpec.cs" />
<Compile Include="PersistentViewSpec.Actors.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReceivePersistentActorTests.cs" />
<Compile Include="ReceivePersistentActorTests_Become.cs" />
<Compile Include="ReceivePersistentActorTests_LifeCycle.cs" />
<Compile Include="SnapshotSpec.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
262 changes: 262 additions & 0 deletions src/core/Akka.Persistence.Tests/ReceivePersistentActorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
//-----------------------------------------------------------------------
// <copyright file="ReceivePersistentActorTests.cs" company="Akka.NET Project">
// Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
// Copyright (C) 2013-2015 Akka.NET project <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using Akka.Actor;
using Akka.Event;
using Akka.TestKit;
using Akka.Util.Internal;
using Xunit;
using Xunit.Abstractions;

namespace Akka.Persistence.Tests
{

public partial class ReceivePersistentActorTests : AkkaSpec
{
public ReceivePersistentActorTests(ITestOutputHelper output = null) : base(output: output)
{
}

[Fact]
public void Given_persistent_actor_with_no_receive_command_specified_When_receiving_message_Then_it_should_be_unhandled()
{
//Given
var pid = "p-1";
WriteEvents(pid, 1, 2, 3);
var actor = Sys.ActorOf(Props.Create(() => new NoCommandActor(pid)), "no-receive-specified");
Sys.EventStream.Subscribe(TestActor, typeof(UnhandledMessage));

//When
actor.Tell("Something");

//Then
ExpectMsg<UnhandledMessage>(m => ((string)m.Message) == "Something" && Equals(m.Recipient, actor));
Sys.EventStream.Unsubscribe(TestActor, typeof(UnhandledMessage));
}

[Fact]
public void Given_persistent_actor_with_no_receive_event_specified_When_receiving_message_Then_it_should_be_unhandled()
{
//Given
var pid = "p-2";
WriteEvents(pid, "Something");

// when
var actor = Sys.ActorOf(Props.Create(() => new NoEventActor(pid)), "no-receive-specified");
Sys.EventStream.Subscribe(TestActor, typeof(UnhandledMessage));

//Then
ExpectMsg<UnhandledMessage>(m => ((string)m.Message) == "Something" && Equals(m.Recipient, actor));
Sys.EventStream.Unsubscribe(TestActor, typeof(UnhandledMessage));
}

[Fact]
public void Test_that_persistent_actor_cannot_call_receive_command_or_receive_event_out_of_construction_and_become()
{
//Given
var pid = "p-3";
WriteEvents(pid, 1, 2, 3);
var actor = Sys.ActorOf(Props.Create(() => new CallReceiveWhenHandlingMessageActor(pid)),"receive-on-handling-message");

//When
actor.Tell("Something that will trigger the actor do call Receive", TestActor);

//Then
//We expect a exception was thrown when the actor called Receive, and that it was sent back to us
ExpectMsg<InvalidOperationException>();
}

[Fact]
public void Given_a_persistent_actor_which_uses_predicates_When_sending_different_messages_Then_correct_handler_should_be_invoked()
{
//Given
var pid = "p-4";
WriteEvents(pid, 1, 2, 3);
var actor = Sys.ActorOf(Props.Create(() => new IntPredicatesActor(pid)) , "predicates");

//When
actor.Tell(0, TestActor);
actor.Tell(5, TestActor);
actor.Tell(10, TestActor);
actor.Tell(15, TestActor);

//Then
ExpectMsg((object) "int<5:0");
ExpectMsg((object) "int<10:5");
ExpectMsg((object) "int<15:10");
ExpectMsg((object) "int:15");
}

[Fact]
public void Given_a_persistent_actor_that_uses_non_generic_and_predicates_When_sending_different_messages_Then_correct_handler_should_be_invoked()
{
//Given
var pid = "p-5";
WriteEvents(pid, 1, 2, 3);
var actor = Sys.ActorOf(Props.Create(() => new TypePredicatesActor(pid)) , "predicates");

//When
actor.Tell(0, TestActor);
actor.Tell(5, TestActor);
actor.Tell(10, TestActor);
actor.Tell(15, TestActor);
actor.Tell("hello", TestActor);

//Then
ExpectMsg((object) "int<5:0");
ExpectMsg((object) "int<10:5");
ExpectMsg((object) "int<15:10");
ExpectMsg((object) "int:15");
ExpectMsg((object) "string:hello");
}


[Fact]
public void Given_a_persistent_actor_with_ReceiveAnyCommand_When_sending_different_messages_Then_correct_handler_should_be_invoked()
{
//Given
var pid = "p-6";
WriteEvents(pid, 1, 2, 3);
var actor = Sys.ActorOf(Props.Create(() => new ReceiveAnyActor(pid)) , "matchany");

//When
actor.Tell(4711, TestActor);
actor.Tell("hello", TestActor);

//Then
ExpectMsg((object)"int:4711");
ExpectMsg((object)"any:hello");
}

private readonly AtomicCounterLong _seqNrCounter = new AtomicCounterLong(1L);
/// <summary>
/// Initialize test journal using provided events.
/// </summary>
private void WriteEvents(string pid, params object[] events)
{
var journalRef = Persistence.Instance.Apply(Sys).JournalFor(string.Empty);
var persistents = events
.Select(e => new Persistent(e, _seqNrCounter.GetAndIncrement(), e.GetType().FullName, pid))
.ToArray();
journalRef.Tell(new WriteMessages(persistents, TestActor, 1));

ExpectMsg<WriteMessagesSuccessful>();
foreach (var p in persistents)
ExpectMsg(new WriteMessageSuccess(p, 1));
}

private abstract class TestReceivePersistentActor : ReceivePersistentActor
{
public readonly LinkedList<object> State = new LinkedList<object>();
private readonly string _persistenceId;

protected TestReceivePersistentActor(string persistenceId)
{
_persistenceId = persistenceId;
}

public override string PersistenceId { get { return _persistenceId; } }
}

private class NoCommandActor : TestReceivePersistentActor
{
public NoCommandActor(string pid) : base(pid)
{
RecoverAny(o => State.AddLast(o));
// no command here
}
}

private class NoEventActor : TestReceivePersistentActor
{
public NoEventActor(string pid) : base(pid)
{
CommandAny(msg => Sender.Tell(msg, Self));
// no recover here
}
}

private class CallReceiveWhenHandlingMessageActor : TestReceivePersistentActor
{
public CallReceiveWhenHandlingMessageActor(string pid) : base(pid)
{
Recover<int>(i => State.AddLast(i));
Command<object>(m =>
{
try
{
Command<int>(i => Sender.Tell(i, Self));
Sender.Tell(null, Self);
}
catch(Exception e)
{
Sender.Tell(e, Self);
}
});
}
}

private class IntPredicatesActor : TestReceivePersistentActor
{
public IntPredicatesActor(string pid) : base(pid)
{
Recover<int>(i => State.AddLast(i));
Command<int>(i => i < 5, i => Sender.Tell("int<5:" + i, Self)); //Predicate first, when i < 5
Command<int>(i => Sender.Tell("int<10:" + i, Self), i => i < 10); //Predicate after, when 5 <= i < 10
Command<int>(i =>
{
if(i < 15)
{
Sender.Tell("int<15:" + i, Self);
return true;
}
return false;
}); //Func, when 10 <= i < 15
Command<int>(i => Sender.Tell("int:" + i, Self), null); //Null predicate, when i >= 15
Command<int>(i => Sender.Tell("ShouldNeverMatch:" + i, Self)); //The handler above should never be invoked
}
}

private class TypePredicatesActor : TestReceivePersistentActor
{
public TypePredicatesActor(string pid) : base(pid)
{
Recover<int>(i => State.AddLast(i));
Command(typeof(int), i => (int)i < 5, i => Sender.Tell("int<5:" + i, Self)); //Predicate first, when i < 5
Command(typeof(int), i => Sender.Tell("int<10:" + i, Self), i => (int)i < 10); //Predicate after, when 5 <= i < 10
Command(typeof(int), o =>
{
var i = (int) o;
if(i < 15)
{
Sender.Tell("int<15:" + i, Self);
return true;
}
return false;
}); //Func, when 10 <= i < 15
Command(typeof(int), i => Sender.Tell("int:" + i, Self), null); //Null predicate, when i >= 15
Command(typeof(int), i => Sender.Tell("ShouldNeverMatch:" + i, Self)); //The handler above should never be invoked
Command(typeof(string), i => Sender.Tell("string:" + i));
}
}


private class ReceiveAnyActor : TestReceivePersistentActor
{
public ReceiveAnyActor(string pid) : base(pid)
{
Command<int>(i => Sender.Tell("int:" + i, Self));
CommandAny(o => Sender.Tell("any:" + o, Self));
}
}

}
}

Loading

0 comments on commit b11dafc

Please sign in to comment.