Additional testing of duplicated extensions (#29013)

* Additional testing of duplicated extensions
* explicit $ in config
* log first problem
This commit is contained in:
Patrik Nordwall 2020-05-12 09:07:16 +02:00 committed by GitHub
parent bada816714
commit 9677f19d2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 14 deletions

View file

@ -34,16 +34,17 @@ object FailingTestExtension extends ExtensionId[FailingTestExtension] with Exten
class TestException extends IllegalArgumentException("ERR") with NoStackTrace
}
object InstanceCountingExtension extends ExtensionId[DummyExtensionImpl] with ExtensionIdProvider {
object InstanceCountingExtension extends ExtensionId[InstanceCountingExtension] with ExtensionIdProvider {
val createCount = new AtomicInteger(0)
override def createExtension(system: ExtendedActorSystem): DummyExtensionImpl = {
createCount.addAndGet(1)
new DummyExtensionImpl
override def createExtension(system: ExtendedActorSystem): InstanceCountingExtension = {
new InstanceCountingExtension
}
override def lookup(): ExtensionId[_ <: Extension] = this
}
class DummyExtensionImpl extends Extension
class InstanceCountingExtension extends Extension {
InstanceCountingExtension.createCount.incrementAndGet()
}
// Dont't place inside ActorSystemSpec object, since it will not be garbage collected and reference to system remains
class FailingTestExtension(val system: ExtendedActorSystem) extends Extension {
@ -111,12 +112,33 @@ class ExtensionSpec extends AnyWordSpec with Matchers {
shutdownActorSystem(system)
}
"allow for auto-loading of library-extensions" in {
"allow for auto-loading of library-extensions from reference.conf" in {
import akka.util.ccompat.JavaConverters._
// could be initialized by other tests, but assuming tests are not running in parallel
val countBefore = InstanceCountingExtension.createCount.get()
val system = ActorSystem("extensions")
val listedExtensions = system.settings.config.getStringList("akka.library-extensions")
listedExtensions.size should be > 0
// could be initialized by other tests, so at least once
InstanceCountingExtension.createCount.get() should be > 0
val listedExtensions = system.settings.config.getStringList("akka.library-extensions").asScala
listedExtensions.count(_.contains("InstanceCountingExtension")) should ===(1)
InstanceCountingExtension.createCount.get() - countBefore should ===(1)
shutdownActorSystem(system)
}
"not create duplicate instances when auto-loading of library-extensions" in {
import akka.util.ccompat.JavaConverters._
// could be initialized by other tests, but assuming tests are not running in parallel
val countBefore = InstanceCountingExtension.createCount.get()
val system = ActorSystem(
"extensions",
ConfigFactory.parseString(
"""
akka.library-extensions = ["akka.actor.InstanceCountingExtension", "akka.actor.InstanceCountingExtension", "akka.actor.InstanceCountingExtension$"]
"""))
val listedExtensions = system.settings.config.getStringList("akka.library-extensions").asScala
listedExtensions.count(_.contains("InstanceCountingExtension")) should ===(3) // testing duplicate names
InstanceCountingExtension.createCount.get() - countBefore should ===(1)
shutdownActorSystem(system)
}

View file

@ -16,7 +16,7 @@ akka.actor.typed {
library-extensions = ${?akka.actor.typed.library-extensions} []
# Receptionist is started eagerly to allow clustered receptionist to gather remote registrations early on.
library-extensions += "akka.actor.typed.receptionist.Receptionist"
library-extensions += "akka.actor.typed.receptionist.Receptionist$"
# While an actor is restarted (waiting for backoff to expire and children to stop)
# incoming messages and signals are stashed, and delivered later to the newly restarted

View file

@ -73,7 +73,7 @@ akka {
#
# Should not be set by end user applications in 'application.conf', use the extensions property for that
#
library-extensions = ${?akka.library-extensions} ["akka.serialization.SerializationExtension"]
library-extensions = ${?akka.library-extensions} ["akka.serialization.SerializationExtension$"]
# List FQCN of extensions which shall be loaded at actor system startup.
# Should be on the format: 'extensions = ["foo", "bar"]' etc.

View file

@ -1178,9 +1178,11 @@ private[akka] class ActorSystemImpl(
* when the extension cannot be found at all we throw regardless of this setting)
*/
def loadExtensions(key: String, throwOnLoadFail: Boolean): Unit = {
immutableSeq(settings.config.getStringList(key)).foreach { fqcn =>
dynamicAccess.getObjectFor[AnyRef](fqcn).recoverWith {
case _ => dynamicAccess.createInstanceFor[AnyRef](fqcn, Nil)
case firstProblem =>
dynamicAccess.createInstanceFor[AnyRef](fqcn, Nil).recoverWith { case _ => Failure(firstProblem) }
} match {
case Success(p: ExtensionIdProvider) =>
registerExtension(p.lookup())

View file

@ -3,7 +3,7 @@
#####################################
# eager creation of the system wide materializer
akka.library-extensions += "akka.stream.SystemMaterializer"
akka.library-extensions += "akka.stream.SystemMaterializer$"
akka {
stream {