Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Cross-compile Akka with Scala 3 #29929

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
.*.swp
.DS_Store
.bloop/
.bsp/
.cache
.classpath
.codefellow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

package akka.pattern;

import akka.actor.Actor;
import akka.actor.ActorRef;
import akka.testkit.AkkaJUnitActorSystemResource;
import akka.testkit.AkkaSpec;
import akka.testkit.TestException;
Expand Down Expand Up @@ -81,7 +81,7 @@ public void testAskWithStatusSuccess() throws Exception {

CompletionStage<Object> response = askWithStatus(probe.ref(), "request", Duration.ofSeconds(3));
probe.expectMsg("request");
probe.lastSender().tell(StatusReply.success("woho"), Actor.noSender());
probe.lastSender().tell(StatusReply.success("woho"), ActorRef.noSender());

Object result = response.toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals("woho", result);
Expand All @@ -93,7 +93,7 @@ public void testAskWithStatusErrorMessage() throws Exception {

CompletionStage<Object> response = askWithStatus(probe.ref(), "request", Duration.ofSeconds(3));
probe.expectMsg("request");
probe.lastSender().tell(StatusReply.error("boho"), Actor.noSender());
probe.lastSender().tell(StatusReply.error("boho"), ActorRef.noSender());

try {
Object result = response.toCompletableFuture().get(3, TimeUnit.SECONDS);
Expand All @@ -110,7 +110,7 @@ public void testAskWithStatusErrorException() throws Exception {

CompletionStage<Object> response = askWithStatus(probe.ref(), "request", Duration.ofSeconds(3));
probe.expectMsg("request");
probe.lastSender().tell(StatusReply.error(new TestException("boho")), Actor.noSender());
probe.lastSender().tell(StatusReply.error(new TestException("boho")), ActorRef.noSender());

try {
Object result = response.toCompletableFuture().get(3, TimeUnit.SECONDS);
Expand Down
3 changes: 3 additions & 0 deletions akka-actor-tests/src/test/scala/akka/AkkaExceptionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import akka.actor._
*/
class AkkaExceptionSpec extends AnyWordSpec with Matchers {

// TODO DOTTY, yes I know it's wrong
implicit val pos: org.scalactic.source.Position = new org.scalactic.source.Position(fileName = "", filePathname = "", lineNumber = 1)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a workaround, ScalaTest is usable with Scala 3, but I found a few rough edges.
The implicit position is provided from a macro in Scala 2.X and is not available in Scala 3.

I see that there is some ongoing work to cross-compile ScalaTest (e.g. scalatest/scalatest@e8201d4 ) and I expect that this issue is solved there, maybe @bvenners or @cheeseng can chip in?

Reference issue:
scalatest/scalatest#1950


"AkkaException" must {
"have a AkkaException(String msg) constructor to be serialization friendly" in {
//if the call to this method completes, we know what there is at least a single constructor which has
Expand Down
3 changes: 3 additions & 0 deletions akka-actor-tests/src/test/scala/akka/AkkaVersionSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import org.scalatest.wordspec.AnyWordSpec

class AkkaVersionSpec extends AnyWordSpec with Matchers {

// TODO DOTTY, yes I know it's wrong
implicit val pos: org.scalactic.source.Position = new org.scalactic.source.Position(fileName = "", filePathname = "", lineNumber = 1)

"The Akka version check" must {

"succeed if version is ok" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class ActorConfigurationVerificationSpec
with BeforeAndAfterEach {
import ActorConfigurationVerificationSpec._

// TODO DOTTY
protected override def runTest(testName: String, args: org.scalatest.Args): org.scalatest.Status = akka.testkit.ScalatestRunTest.scalatestRunTest(testName, args)

override def atStartup(): Unit = {
system.eventStream.publish(Mute(EventFilter[ConfigurationException]("")))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ object ActorLifeCycleSpec {
class ActorLifeCycleSpec extends AkkaSpec with BeforeAndAfterEach with ImplicitSender with DefaultTimeout {
import ActorLifeCycleSpec._

// TODO DOTTY
protected override def runTest(testName: String, args: org.scalatest.Args): org.scalatest.Status = akka.testkit.ScalatestRunTest.scalatestRunTest(testName, args)

"An Actor" must {

"invoke preRestart, preStart, postRestart when using OneForOneStrategy" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,12 @@ class ActorMailboxSpec(conf: Config) extends AkkaSpec(conf) with DefaultTimeout

actor ! "ping"
val q = expectMsgType[MessageQueue]
types.foreach(t => assert(t.isInstance(q), s"Type [${q.getClass.getName}] is not assignable to [${t.getName}]"))
// TODO DOTTY
import scala.language.postfixOps
types.foreach(t =>
// require(t.isInstance(q), s"Type [${q.getClass.getName}] is not assignable to [${t.getName}]")
t.isInstance(q).shouldBe(true)
)
q
}

Expand Down
34 changes: 19 additions & 15 deletions akka-actor-tests/src/test/scala/akka/actor/ActorPathSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import org.scalatest.wordspec.AnyWordSpec

class ActorPathSpec extends AnyWordSpec with Matchers {

// TODO DOTTY, yes I know it's wrong
implicit val pos: org.scalactic.source.Position = new org.scalactic.source.Position(fileName = "", filePathname = "", lineNumber = 1)

"An ActorPath" must {

"support parsing its String rep" in {
Expand Down Expand Up @@ -59,9 +62,10 @@ class ActorPathSpec extends AnyWordSpec with Matchers {

"create correct toStringWithAddress" in {
val local = Address("akka", "mysys")
val a = local.copy(host = Some("aaa"), port = Some(2552))
val b = a.copy(host = Some("bb"))
val c = a.copy(host = Some("cccc"))
// TODO DOTTY
val a = Address("akka", "mysys", host = "aaa", port = 2552)
val b = Address("akka", "mysys", host = "bb", port = 2552)
val c = Address("akka", "mysys", host = "cccc", port = 2552)
val root = RootActorPath(local)
root.toStringWithAddress(a) should ===("akka://mysys@aaa:2552/")
(root / "user").toStringWithAddress(a) should ===("akka://mysys@aaa:2552/user")
Expand Down Expand Up @@ -92,31 +96,31 @@ class ActorPathSpec extends AnyWordSpec with Matchers {

"detect valid and invalid chars in host names when not using AddressFromURIString, e.g. docker host given name" in {
Seq(
Address("akka", "sys", Some("valid"), Some(0)),
Address("akka", "sys", Some("is_valid.org"), Some(0)),
Address("akka", "sys", Some("fu.is_valid.org"), Some(0))).forall(_.hasInvalidHostCharacters) shouldBe false
Address("akka", "sys", "valid", 0),
Address("akka", "sys", "is_valid.org", 0),
Address("akka", "sys", "fu.is_valid.org", 0)).forall(_.hasInvalidHostCharacters) shouldBe false

Seq(Address("akka", "sys", Some("in_valid"), Some(0)), Address("akka", "sys", Some("invalid._org"), Some(0)))
Seq(Address("akka", "sys", "in_valid", 0), Address("akka", "sys", "invalid._org", 0))
.forall(_.hasInvalidHostCharacters) shouldBe true

intercept[MalformedURLException](AddressFromURIString("akka://sys@in_valid:5001"))
}

"not fail fast if the check is called on valid chars in host names" in {
Seq(
Address("akka", "sys", Some("localhost"), Some(0)),
Address("akka", "sys", Some("is_valid.org"), Some(0)),
Address("akka", "sys", Some("fu.is_valid.org"), Some(0))).foreach(_.checkHostCharacters())
Address("akka", "sys", "localhost", 0),
Address("akka", "sys", "is_valid.org", 0),
Address("akka", "sys", "fu.is_valid.org", 0)).foreach(_.checkHostCharacters())
}

"fail fast if the check is called when invalid chars are in host names" in {
Seq(
Address("akka", "sys", Some("localhost"), Some(0)),
Address("akka", "sys", Some("is_valid.org"), Some(0)),
Address("akka", "sys", Some("fu.is_valid.org"), Some(0))).foreach(_.checkHostCharacters())
Address("akka", "sys", "localhost", 0),
Address("akka", "sys", "is_valid.org", 0),
Address("akka", "sys", "fu.is_valid.org", 0)).foreach(_.checkHostCharacters())

intercept[IllegalArgumentException](Address("akka", "sys", Some("in_valid"), Some(0)).checkHostCharacters())
intercept[IllegalArgumentException](Address("akka", "sys", Some("invalid._org"), Some(0)).checkHostCharacters())
intercept[IllegalArgumentException](Address("akka", "sys", "in_valid", 0).checkHostCharacters())
intercept[IllegalArgumentException](Address("akka", "sys", "invalid._org", 0).checkHostCharacters())
}
}
}
4 changes: 2 additions & 2 deletions akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -466,8 +466,8 @@ class ActorRefSpec extends AkkaSpec("""
def receive = { case name: String => sender() ! context.child(name).isDefined }
}), "parent")

assert(Await.result((parent ? "child"), timeout.duration) === true)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert is a macro and is not usable "as is", for the moment I switched to require, but I was expecting this to work out of the box, maybe @nicolasstucki or @smarter can shed a light?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the issue with assert?

Copy link
Contributor Author

@andreaTP andreaTP Jan 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since assert is a macro Scala 3 rejects it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolasstucki there's no actual issue, this project is just using a scala 2 version of scalatest instead of the scala 3 version: #29929 (comment)

assert(Await.result((parent ? "whatnot"), timeout.duration) === false)
require(Await.result((parent ? "child"), timeout.duration) === true)
require(Await.result((parent ? "whatnot"), timeout.duration) === false)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,17 @@ object ActorSystemSpec {
override def dispatcher(): MessageDispatcher = instance
}

val config = s"""
// TODO DOTTY
val configStr = s"""
slow {
type="${classOf[SlowDispatcher].getName}"
}"""

}

// TODO DOTTY
@silent
class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.config) with ImplicitSender {
class ActorSystemSpec extends AkkaSpec(ActorSystemSpec.configStr) with ImplicitSender {

import ActorSystemSpec.FastActor

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class ActorWithBoundedStashSpec
with ImplicitSender {
import ActorWithBoundedStashSpec._

// TODO DOTTY
protected override def runTest(testName: String, args: org.scalatest.Args): org.scalatest.Status = akka.testkit.ScalatestRunTest.scalatestRunTest(testName, args)

override def atStartup(): Unit = {
system.eventStream.publish(Mute(EventFilter.warning(pattern = ".*received dead letter from.*hello.*")))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ object ActorWithStashSpec {
class ActorWithStashSpec extends AkkaSpec with DefaultTimeout with BeforeAndAfterEach {
import ActorWithStashSpec._

// TODO DOTTY
protected override def runTest(testName: String, args: org.scalatest.Args): org.scalatest.Status = akka.testkit.ScalatestRunTest.scalatestRunTest(testName, args)

override def atStartup(): Unit = {
system.eventStream.publish(Mute(EventFilter[Exception]("Crashing...")))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,13 @@ class CoordinatedShutdownSpec
val task2 = co.addCancellableTask("a", "copy2")(createTask("copy2"))
val task3 = co.addCancellableTask("a", "copy3")(createTask("copy3"))

assert(!task1.isCancelled)
assert(!task2.isCancelled)
assert(!task3.isCancelled)
// TODO DOTTY
require(!task1.isCancelled)
require(!task2.isCancelled)
require(!task3.isCancelled)

task2.cancel()
assert(task2.isCancelled)
require(task2.isCancelled)

val messagesFut = Future {
probe.receiveN(2, 3.seconds).map(_.toString)
Expand Down Expand Up @@ -205,11 +206,11 @@ class CoordinatedShutdownSpec
val task3 = co.addCancellableTask("a", taskName)(task)

List(task1, task2, task3).foreach { t =>
assert(!t.isCancelled)
require(!t.isCancelled)
}

task1.cancel()
assert(task1.isCancelled)
require(task1.isCancelled)

val messagesFut = Future {
testProbe.receiveN(2, 3.seconds).map(_.toString)
Expand Down
12 changes: 10 additions & 2 deletions akka-actor-tests/src/test/scala/akka/actor/DynamicAccessSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ class TestClassWithDefaultConstructor extends TestSuperclass {
class DynamicAccessSpec extends AnyWordSpec with Matchers with BeforeAndAfterAll {
val system = ActorSystem()

// TODO DOTTY, yes I know it's wrong
implicit val pos: org.scalactic.source.Position = new org.scalactic.source.Position(fileName = "", filePathname = "", lineNumber = 1)

// TODO DOTTY
protected override def runTest(testName: String, args: org.scalatest.Args): org.scalatest.Status = akka.testkit.ScalatestRunTest.scalatestRunTest(testName, args)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is again regarding ScalaTest, I would love to know if there is a better way of doing it.
cc. @bvenners @cheeseng

override def run(testName: Option[String], args: org.scalatest.Args): org.scalatest.Status = akka.testkit.ScalatestRunTest.scalatestRun(testName, args)

"The DynamicAccess of a system" should {
val dynamicAccess = system.asInstanceOf[ExtendedActorSystem].dynamicAccess

Expand All @@ -42,7 +49,8 @@ class DynamicAccessSpec extends AnyWordSpec with Matchers with BeforeAndAfterAll
case Success(instance) =>
fail(s"Expected failure, found $instance")
case Failure(e) =>
e shouldBe a[ClassNotFoundException]
// TODO DOTTY
e.getClass shouldBe classOf[ClassNotFoundException]
}
}

Expand All @@ -51,7 +59,7 @@ class DynamicAccessSpec extends AnyWordSpec with Matchers with BeforeAndAfterAll
instantiateWithDefaultOrStringCtor("akka.actor.TestClassWithDefaultConstructor").get.name shouldBe "default"
instantiateWithDefaultOrStringCtor("akka.actor.foo.NonExistingClass") match {
case Failure(t) =>
t shouldBe a[ClassNotFoundException]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ScalaTest related type check is done via a macro.
cc. @bvenners @cheeseng

t.getClass shouldBe classOf[ClassNotFoundException]
case Success(instance) =>
fail(s"unexpected instance $instance")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class FailingTestExtension(val system: ExtendedActorSystem) extends Extension {

class ExtensionSpec extends AnyWordSpec with Matchers {

// TODO DOTTY, yes I know it's wrong
implicit val pos: org.scalactic.source.Position = new org.scalactic.source.Position(fileName = "", filePathname = "", lineNumber = 1)

"The ActorSystem extensions support" should {

"support extensions" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,11 @@ class LocalActorRefProviderSpec extends AkkaSpec(LocalActorRefProviderSpec.confi
case Some(Failure(_: InvalidActorNameException)) => 2
case x => x
})
set should ===(Set[Any](1, 2))
// TODO DOTTY
// set should ===(Set[Any](1, 2))
set.getClass shouldBe classOf[Set[Any]]
set(0) shouldBe(1)
set(1) shouldBe(2)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import com.typesafe.config.ConfigFactory
import akka.actor.ActorSystem.Settings
import akka.actor.ActorSystem.findClassLoader
import akka.actor.setup.ActorSystemSetup
import akka.testkit.AbstractSpec
// TODO DOTTY AbstractSpec doesn't work? strange errors
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class ProviderSelectionSpec extends AbstractSpec {
class ProviderSelectionSpec extends AnyWordSpec with Matchers {
import ProviderSelection.{ ClusterActorRefProvider, RemoteActorRefProvider }

// TODO DOTTY, yes I know it's wrong
implicit val pos: org.scalactic.source.Position = new org.scalactic.source.Position(fileName = "", filePathname = "", lineNumber = 1)

"ProviderSelection" must {

val setup = ActorSystemSetup()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import org.scalatest.wordspec.AnyWordSpec

class RelativeActorPathSpec extends AnyWordSpec with Matchers {

// TODO DOTTY, yes I know it's wrong
implicit val pos: org.scalactic.source.Position = new org.scalactic.source.Position(fileName = "", filePathname = "", lineNumber = 1)

def elements(path: String): immutable.Seq[String] = RelativeActorPath.unapply(path).getOrElse(Nil)

"RelativeActorPath" must {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout {
employee ! Crash
}
Await.ready(countDownLatch, 2 minutes)
assert(!employee.isTerminated)
require(!employee.isTerminated)
}

"ensure that employee restarts after number of crashes not within time range" in {
Expand Down Expand Up @@ -158,7 +158,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout {

Await.ready(thirdRestartLatch, 1 second)

assert(!employee.isTerminated)
require(!employee.isTerminated)
}

"ensure that employee is not restarted after max retries" in {
Expand Down Expand Up @@ -195,7 +195,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout {
// test restart and post restart ping
Await.ready(restartLatch, 10 seconds)

assert(!employee.isTerminated)
require(!employee.isTerminated)

// now crash again... should not restart
employee ! Crash
Expand All @@ -209,7 +209,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout {
employee ! Crash
Await.ready(stopLatch, 10 seconds)
sleep(500L)
assert(employee.isTerminated)
require(employee.isTerminated)
}

"ensure that employee is not restarted within time range" in {
Expand Down Expand Up @@ -248,7 +248,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout {
// test restart and post restart ping
Await.ready(restartLatch, 10 seconds)

assert(!employee.isTerminated)
require(!employee.isTerminated)

// now crash again... should not restart
employee ! Crash
Expand All @@ -264,7 +264,7 @@ class RestartStrategySpec extends AkkaSpec with DefaultTimeout {

Await.ready(maxNoOfRestartsLatch, 10 seconds)
sleep(500L)
assert(employee.isTerminated)
require(employee.isTerminated)
}
}
}