pekko/akka-actor-tests/src/test/java/akka/japi/pf/ReceiveBuilderTest.java
Seth Tisue fc23f03031 upgrade to latest ScalaTest (#26387)
stuff moved to a new package. you wouldn't expect that in a point
release, but they put type aliases in place so Scala users wouldn't
notice. but the change is visible to Java code.

the upgrade is not strictly necessary, but it would be convenient
for the Scala 2.13 community build to have this merged, so I don't
have to maintain these changes in our Akka fork
2019-02-17 19:45:39 +00: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.scalatestplus.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");
}
}