Merge pull request #27701 from akka/wip-occurence0-patriknw

wait for async excess events when occurrences 0
This commit is contained in:
Patrik Nordwall 2019-09-26 12:00:38 +02:00 committed by GitHub
commit ae32f1431a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 5 deletions

View file

@ -75,17 +75,29 @@ import org.slf4j.event.Level
todo == Int.MaxValue || todo == 0 todo == Int.MaxValue || todo == 0
} }
private def awaitNoExcess(max: Duration): Boolean = {
if (todo == 0)
!TestKit.awaitCond(todo < 0, max, noThrow = true)
else
todo > 0
}
override def intercept[T](code: => T)(implicit system: ActorSystem[_]): T = { override def intercept[T](code: => T)(implicit system: ActorSystem[_]): T = {
val effectiveLoggerName = loggerName.getOrElse("") val effectiveLoggerName = loggerName.getOrElse("")
checkLogback(system) checkLogback(system)
TestAppender.setupTestAppender(effectiveLoggerName) TestAppender.setupTestAppender(effectiveLoggerName)
TestAppender.addFilter(effectiveLoggerName, this) TestAppender.addFilter(effectiveLoggerName, this)
val leeway = TestKitSettings(system).FilterLeeway val settings = TestKitSettings(system)
try { try {
val result = code val result = code
if (!awaitDone(leeway))
// wait some more when occurrences=0 to find asynchronous exceess messages
if (occurrences == 0)
awaitNoExcess(settings.ExpectNoMessageDefaultTimeout)
if (!awaitDone(settings.FilterLeeway))
if (todo > 0) if (todo > 0)
throw new AssertionError(s"Timeout ($leeway) waiting for $todo messages on $this.") throw new AssertionError(s"Timeout (${settings.FilterLeeway}) waiting for $todo messages on $this.")
else else
throw new AssertionError(s"Received ${-todo} excess messages on $this.") throw new AssertionError(s"Received ${-todo} excess messages on $this.")
result result

View file

@ -26,6 +26,13 @@ import org.slf4j.event.Level
/** /**
* Number of events the filter is supposed to match. By default 1. * Number of events the filter is supposed to match. By default 1.
*
* When occurrences > 0 it will not look for excess messages that are logged asynchronously
* outside (after) the `intercept` thunk and it has already found expected number.
*
* When occurrences is 0 it will look for unexpected matching events, and then it will
* also look for excess messages during the configured `akka.actor.testkit.typed.expect-no-message-default`
* duration.
*/ */
def withOccurrences(newOccurrences: Int): LoggingEventFilter def withOccurrences(newOccurrences: Int): LoggingEventFilter

View file

@ -26,6 +26,13 @@ import org.slf4j.event.Level
/** /**
* Number of events the filter is supposed to match. By default 1. * Number of events the filter is supposed to match. By default 1.
*
* When occurrences > 0 it will not look for excess messages that are logged asynchronously
* outside (after) the `intercept` thunk and it has already found expected number.
*
* When occurrences is 0 it will look for unexpected matching events, and then it will
* also look for excess messages during the configured `akka.actor.testkit.typed.expect-no-message-default`
* duration.
*/ */
def withOccurrences(newOccurrences: Int): LoggingEventFilter def withOccurrences(newOccurrences: Int): LoggingEventFilter

View file

@ -6,11 +6,20 @@ package akka.actor.testkit.typed.scaladsl
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import scala.concurrent.Future
import akka.actor.testkit.typed.TestException import akka.actor.testkit.typed.TestException
import org.scalatest.WordSpecLike import org.scalatest.WordSpecLike
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
class TestAppenderSpec extends ScalaTestWithActorTestKit with WordSpecLike with LogCapturing { class TestAppenderSpec
extends ScalaTestWithActorTestKit(
"""
# increase to avoid spurious failures in "find unexpected async events withOccurrences(0)"
akka.actor.testkit.typed.expect-no-message-default = 1000 ms
""")
with WordSpecLike
with LogCapturing {
class AnotherLoggerClass class AnotherLoggerClass
@ -39,6 +48,21 @@ class TestAppenderSpec extends ScalaTestWithActorTestKit with WordSpecLike with
} }
} }
"find excess messages" in {
intercept[AssertionError] {
LoggingEventFilter.warn("a warning").withOccurrences(2).intercept {
log.error("an error")
log.warn("a warning")
log.warn("a warning")
log.error("an error")
// since this logging is synchronous it will notice 3 occurrences but expecting 2,
// but note that it will not look for asynchronous excess messages when occurrences > 0 and it has
// already found expected number
log.warn("a warning") // 3rd
}
}.getMessage should include("Received 1 excess messages")
}
"only filter events for given logger name" in { "only filter events for given logger name" in {
val count = new AtomicInteger val count = new AtomicInteger
LoggingEventFilter LoggingEventFilter
@ -57,7 +81,7 @@ class TestAppenderSpec extends ScalaTestWithActorTestKit with WordSpecLike with
count.get should ===(2) count.get should ===(2)
} }
"find unexpected events withOccurences(0)" in { "find unexpected events withOccurrences(0)" in {
LoggingEventFilter.warn("a warning").withOccurrences(0).intercept { LoggingEventFilter.warn("a warning").withOccurrences(0).intercept {
log.error("an error") log.error("an error")
log.warn("another warning") log.warn("another warning")
@ -77,6 +101,20 @@ class TestAppenderSpec extends ScalaTestWithActorTestKit with WordSpecLike with
log.warn("a warning") log.warn("a warning")
} }
}.getMessage should include("Received 2 excess messages") }.getMessage should include("Received 2 excess messages")
}
"find unexpected async events withOccurrences(0)" in {
// expect-no-message-default = 1000 ms
intercept[AssertionError] {
LoggingEventFilter.warn("a warning").withOccurrences(0).intercept {
Future {
Thread.sleep(20)
log.warn("a warning")
log.warn("a warning")
}(system.executionContext)
}
}
} }
} }