pekko/akka-actor-tests/src/test/java/akka/japi/pf/ReceiveBuilderTest.java
2019-03-19 11:25:48 +01:00

279 lines
7.8 KiB
Java

/*
* Copyright (C) 2017-2019 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.japi.pf;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.Before;
import org.scalatest.junit.JUnitSuite;
import akka.actor.AbstractActor.Receive;
import static org.junit.Assert.*;
@SuppressWarnings("serial")
public class ReceiveBuilderTest extends JUnitSuite {
public static interface Msg {}
public static class Msg1 implements Msg {
@Override
public String toString() {
return "Msg1";
}
}
public static class Msg2 implements Msg {
public final String value;
public Msg2(String value) {
this.value = value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Msg2 other = (Msg2) obj;
if (value == null) {
if (other.value != null) return false;
} else if (!value.equals(other.value)) return false;
return true;
}
@Override
public String toString() {
return "Msg2 [value=" + value + "]";
}
}
// using instance variable, because lambdas can only modify final fields
private String result = "";
private String result() {
String r = result;
result = "";
return r;
}
private void result(String r) {
result = r;
}
@Before
public void beforeEach() {
result = "";
}
@Test
public void shouldNotMatchWhenEmpty() {
Receive rcv = ReceiveBuilder.create().build();
assertFalse(rcv.onMessage().isDefinedAt("hello"));
assertFalse(rcv.onMessage().isDefinedAt(42));
}
@Test
public void shouldMatchByClass() {
Receive rcv = ReceiveBuilder.create().match(Msg1.class, m -> result("match Msg1")).build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg1()));
rcv.onMessage().apply(new Msg1());
assertEquals("match Msg1", result());
assertFalse(rcv.onMessage().isDefinedAt(new Msg2("foo")));
assertFalse(rcv.onMessage().isDefinedAt("hello"));
assertFalse(rcv.onMessage().isDefinedAt(42));
}
@Test
public void shouldMatchBySubclass() {
Receive rcv = ReceiveBuilder.create().match(Msg.class, m -> result("match Msg")).build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg1()));
rcv.onMessage().apply(new Msg1());
assertEquals("match Msg", result());
assertTrue(rcv.onMessage().isDefinedAt(new Msg2("foo")));
rcv.onMessage().apply(new Msg2("foo"));
assertEquals("match Msg", result());
assertFalse(rcv.onMessage().isDefinedAt("hello"));
assertFalse(rcv.onMessage().isDefinedAt(42));
}
private void handleMsg(Msg msg) {
result("match Msg");
}
private void handleMsg(Msg1 msg) {
result("match Msg1");
}
private void handleMsg(Msg2 msg) {
result("match Msg2");
}
@Test
public void shouldMatchDelegatingToSpecificMethod() {
Receive rcv =
ReceiveBuilder.create()
.match(Msg1.class, this::handleMsg)
.match(Msg2.class, this::handleMsg)
.match(Msg.class, this::handleMsg)
.build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg1()));
rcv.onMessage().apply(new Msg1());
assertEquals("match Msg1", result());
assertTrue(rcv.onMessage().isDefinedAt(new Msg2("foo")));
rcv.onMessage().apply(new Msg2("foo"));
assertEquals("match Msg2", result());
}
private void anotherHandleMsg(Msg msg) {
result("match Msg");
}
private void anotherHandleMsg(Msg1 msg) {
result("match Msg1");
}
@Test
public void shouldMatchDelegatingToGeneralMethod() {
Receive rcv =
ReceiveBuilder.create()
.match(Msg1.class, this::anotherHandleMsg)
.match(Msg2.class, this::anotherHandleMsg)
.build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg1()));
rcv.onMessage().apply(new Msg1());
assertEquals("match Msg1", result());
assertTrue(rcv.onMessage().isDefinedAt(new Msg2("foo")));
rcv.onMessage().apply(new Msg2("foo"));
assertEquals("match Msg", result());
}
@Test
public void shouldMatchByPredicate() {
Receive rcv =
ReceiveBuilder.create()
.match(Msg1.class, m -> true, m -> result("match Msg1"))
.match(Msg2.class, m -> m.value.equals("foo"), m -> result("match Msg2"))
.build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg1()));
rcv.onMessage().apply(new Msg1());
assertEquals("match Msg1", result());
assertTrue(rcv.onMessage().isDefinedAt(new Msg2("foo")));
rcv.onMessage().apply(new Msg2("foo"));
assertEquals("match Msg2", result());
assertFalse(rcv.onMessage().isDefinedAt(new Msg2("bar")));
assertFalse(rcv.onMessage().isDefinedAt("hello"));
assertFalse(rcv.onMessage().isDefinedAt(42));
}
private boolean externalPredicateAlwaysTrue() {
return true;
}
@Test
public void shouldMatchByExternalPredicate() {
Receive rcv =
ReceiveBuilder.create()
.match(Msg1.class, this::externalPredicateAlwaysTrue, m -> result("match Msg1"))
.build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg1()));
rcv.onMessage().apply(new Msg1());
assertEquals("match Msg1", result());
assertFalse(rcv.onMessage().isDefinedAt(new Msg2("foo")));
}
@Test
public void shouldMatchEquals() {
Msg2 msg2 = new Msg2("foo");
Receive rcv =
ReceiveBuilder.create()
.matchEquals(msg2, m -> result("match msg2"))
.matchEquals("foo", m -> result("match foo"))
.matchEquals(17, m -> result("match 17"))
.build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg2("foo")));
rcv.onMessage().apply(new Msg2("foo"));
assertEquals("match msg2", result());
assertTrue(rcv.onMessage().isDefinedAt("foo"));
rcv.onMessage().apply("foo");
assertEquals("match foo", result());
assertTrue(rcv.onMessage().isDefinedAt(17));
rcv.onMessage().apply(17);
assertEquals("match 17", result());
assertFalse(rcv.onMessage().isDefinedAt(new Msg2("bar")));
assertFalse(rcv.onMessage().isDefinedAt("hello"));
assertFalse(rcv.onMessage().isDefinedAt(42));
}
@Test
public void shouldMatchAny() {
Receive rcv =
ReceiveBuilder.create()
.match(Msg1.class, m -> result("match Msg1"))
.matchAny(m -> result("match any"))
.build();
assertTrue(rcv.onMessage().isDefinedAt(new Msg1()));
rcv.onMessage().apply(new Msg1());
assertEquals("match Msg1", result());
assertTrue(rcv.onMessage().isDefinedAt(new Msg2("foo")));
rcv.onMessage().apply(new Msg2("foo"));
assertEquals("match any", result());
assertTrue(rcv.onMessage().isDefinedAt("hello"));
assertTrue(rcv.onMessage().isDefinedAt(42));
}
@Test
public void shouldMatchUnchecked() {
Receive rcv =
ReceiveBuilder.create()
.matchUnchecked(
List.class,
(List<String> list) -> {
result("match List");
})
.build();
List<String> list = Arrays.asList("foo");
assertTrue(rcv.onMessage().isDefinedAt(list));
rcv.onMessage().apply(list);
assertEquals("match List", result());
}
@Test(expected = ClassCastException.class)
public void shouldThrowWhenUncheckedWithWrongTypes() {
// note that this doesn't compile with ordinary match
Receive rcv =
ReceiveBuilder.create()
.matchUnchecked(
String.class,
(Integer i) -> {
result(String.valueOf(i + 2));
})
.build();
assertTrue(rcv.onMessage().isDefinedAt("foo"));
rcv.onMessage().apply("foo");
}
}