Adds 'exists' and 'contains' method to StashBuffer (#29870)

This commit is contained in:
Renato Cavalcanti 2020-12-14 14:20:31 +01:00 committed by GitHub
parent 268b46c8a8
commit 77f242269a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 8 deletions

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2020 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.actor.typed.javadsl;
import akka.actor.testkit.typed.internal.StubbedActorContext;
import akka.actor.testkit.typed.javadsl.LogCapturing;
import akka.actor.typed.internal.StashBufferImpl;
import org.junit.Rule;
import org.junit.Test;
import org.scalatestplus.junit.JUnitSuite;
import java.util.function.Function;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class StashBufferTest extends JUnitSuite {
@Rule public final LogCapturing logCapturing = new LogCapturing();
StubbedActorContext<String> context =
new StubbedActorContext<String>(
"StashBufferTest",
() -> {
throw new UnsupportedOperationException("Will never be invoked in this test");
});
@Test
public void testProcessElementsInTheRightOrder() {
StashBuffer<String> buffer = StashBufferImpl.apply(context, 10);
buffer.stash("m1");
buffer.stash("m2");
buffer.stash("m3");
StringBuilder sb1 = new StringBuilder();
buffer.forEach(sb1::append);
assertEquals("m1m2m3", sb1.toString());
buffer.unstash(Behaviors.ignore(), 1, Function.identity());
StringBuilder sb2 = new StringBuilder();
buffer.forEach(sb2::append);
assertEquals("m2m3", sb2.toString());
}
@Test
public void testAnyMatchAndContains() {
StashBuffer<String> buffer = StashBufferImpl.apply(context, 10);
buffer.stash("m1");
buffer.stash("m2");
assertTrue(buffer.anyMatch(m -> m.startsWith("m")));
assertTrue(buffer.anyMatch(m -> m.endsWith("2")));
assertTrue(buffer.contains("m1"));
assertTrue(buffer.contains("m2"));
}
}

View file

@ -81,6 +81,18 @@ class StashBufferSpec extends AnyWordSpec with Matchers with LogCapturing {
sb2.toString() should ===("m2m3")
}
"answer 'exists' and 'contains' correctly" in {
val buffer = StashBuffer[String](context, 10)
buffer.stash("m1")
buffer.stash("m2")
buffer.contains("m1") shouldBe true
buffer.exists(_ == "m2") shouldBe true
buffer.contains("m3") shouldBe false
buffer.exists(_ == "m4") shouldBe false
}
"unstash to returned behaviors" in {
val buffer = StashBuffer[String](context, 10)
buffer.stash("m1")

View file

@ -0,0 +1,4 @@
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.javadsl.StashBuffer.contains")
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.javadsl.StashBuffer.anyMatch")
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.scaladsl.StashBuffer.contains")
ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.actor.typed.scaladsl.StashBuffer.exists")

View file

@ -5,10 +5,8 @@
package akka.actor.typed.internal
import java.util.function.{ Function => JFunction }
import scala.annotation.tailrec
import scala.util.control.NonFatal
import akka.actor.DeadLetter
import akka.actor.typed.Behavior
import akka.actor.typed.Signal
@ -17,7 +15,7 @@ import akka.actor.typed.javadsl
import akka.actor.typed.scaladsl
import akka.actor.typed.scaladsl.ActorContext
import akka.annotation.{ InternalApi, InternalStableApi }
import akka.japi.function.Procedure
import akka.japi.function.{ Predicate, Procedure }
import akka.util.{ unused, ConstantFun }
import akka.util.OptionVal
@ -128,6 +126,21 @@ import akka.util.OptionVal
override def forEach(f: Procedure[T]): Unit = foreach(f.apply)
override def contains[U >: T](message: U): Boolean =
exists(_ == message)
override def exists(predicate: T => Boolean): Boolean = {
var hasElement = false
var node = _first
while (node != null && !hasElement) {
hasElement = predicate(node.message)
node = node.next
}
hasElement
}
override def anyMatch(predicate: Predicate[T]): Boolean = exists(predicate.test)
override def unstashAll(behavior: Behavior[T]): Behavior[T] = {
val behav = unstash(behavior, size, ConstantFun.scalaIdentityFunction[T])
stashCleared(ctx)

View file

@ -4,12 +4,11 @@
package akka.actor.typed.javadsl
import java.util.function.{ Function => JFunction }
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl
import akka.actor.typed.{ scaladsl, Behavior }
import akka.annotation.DoNotInherit
import akka.japi.function.Procedure
import akka.japi.function.{ Predicate, Procedure }
import java.util.function.{ Function => JFunction }
/**
* A non thread safe mutable message buffer that can be used to buffer messages inside actors
@ -81,6 +80,22 @@ import akka.japi.function.Procedure
*/
def forEach(f: Procedure[T]): Unit
/**
* Tests whether this [[StashBuffer]] contains a given message.
*
* @param message the message to test
* @return true if the buffer contains the message, false otherwise.
*/
def contains[U >: T](message: U): Boolean
/**
* Tests whether a predicate holds for at least one element of this [[StashBuffer]].
*
* @param predicate the predicate used to test
* @return true if the predicate holds for at least one message, false otherwise.
*/
def anyMatch(predicate: Predicate[T]): Boolean
/**
* Removes all messages from the buffer.
*/

View file

@ -92,6 +92,22 @@ import akka.annotation.{ DoNotInherit, InternalApi }
*/
def foreach(f: T => Unit): Unit
/**
* Tests whether this [[StashBuffer]] contains a given message.
*
* @param message the message to test
* @return true if the buffer contains the message, false otherwise.
*/
def contains[U >: T](message: U): Boolean
/**
* Tests whether a predicate holds for at least one element of this [[StashBuffer]].
*
* @param predicate the predicate used to test
* @return true if the predicate holds for at least one message, false otherwise.
*/
def exists(predicate: T => Boolean): Boolean
/**
* Removes all messages from the buffer.
*/