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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala-native support #568

Merged
merged 22 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ on:
branches: ["master", "series/*"]
tags: ["v*"]

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: Test ${{matrix.scalaVersion}} (${{matrix.scalaPlatform}})
Expand All @@ -16,7 +20,7 @@ jobs:
os: [ubuntu-latest]
java: [adopt@1.8]
scalaVersion: ["2_12", "2_13", "3"]
scalaPlatform: ["jvm", "js"]
scalaPlatform: ["jvm", "js", "native"]
runs-on: ${{ matrix.os }}
env:
BUILD_KEY: ${{matrix.scalaVersion}}_${{matrix.scalaPlatform}}
Expand Down
3 changes: 3 additions & 0 deletions .sbtopts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-J-Xms2g
-J-Xmx4g
-J-XX:MaxMetaspaceSize=512m
13 changes: 9 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ sonatypeCredentialHost := "s01.oss.sonatype.org"

val Version = new {
object CE3 {
val fs2 = "3.2.12"
val cats = "3.3.14"
val fs2 = "3.2.14-75-7902cbf"
keynmol marked this conversation as resolved.
Show resolved Hide resolved
val cats = "3.3.14-1-5d11fe9"
keynmol marked this conversation as resolved.
Show resolved Hide resolved
val zioInterop = "3.2.9.1"
}

val expecty = "0.15.4"
val expecty = "0.16.0"
val portableReflect = "1.1.2"
val junit = "4.13.2"
val scalajsStubs = "1.1.0"
Expand Down Expand Up @@ -204,10 +204,15 @@ lazy val framework = projectMatrix
"org.scala-sbt" % "test-interface" % Version.testInterface,
"org.scala-js" %%% "scalajs-stubs" % Version.scalajsStubs % "provided" cross CrossVersion.for3Use2_13
)
else
else if (virtualAxes.value.contains(VirtualAxis.js))
Seq(
"org.scala-js" %% "scalajs-test-interface" % scalaJSVersion cross CrossVersion.for3Use2_13
)
else if (virtualAxes.value.contains(VirtualAxis.native))
Seq(
"org.scala-native" %%% "test-interface" % nativeVersion
)
else Seq.empty
} ++ Seq("junit" % "junit" % Version.junit)
)
.settings(WeaverPlugin.simpleLayout)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import cats.effect.IO
private[weaver] trait CatsUnsafeRunPlatformCompat {
self: CatsUnsafeRun =>

def sync(task: IO[Unit]): Unit = ???
def unsafeRunSync(task: IO[Unit]): Unit = ???

def background(task: IO[Unit]): CancelToken = ???

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import cats.effect.unsafe.implicits.global

private[weaver] trait CatsUnsafeRunPlatformCompat { self: CatsUnsafeRun =>

def sync(task: IO[Unit]): Unit = task.unsafeRunSync()
def unsafeRunSync(task: IO[Unit]): Unit = task.unsafeRunSync()

def background(task: IO[Unit]): CancelToken =
task.start.unsafeRunSync()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package weaver

import scala.concurrent.Await
import scala.concurrent.duration._

import cats.effect.IO
import cats.effect.unsafe.implicits.global

private[weaver] trait CatsUnsafeRunPlatformCompat {
self: CatsUnsafeRun =>

def unsafeRunSync(task: IO[Unit]): Unit = {
val future = task.unsafeToFuture()
scalanative.runtime.loop()
Await.result(future, 1.minute)
}

def background(task: IO[Unit]): CancelToken = ???

}
7 changes: 5 additions & 2 deletions modules/core/cats/src/weaver/CatsUnsafeRun.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package weaver

import scala.concurrent.Future

import cats.effect.unsafe.implicits.global
import cats.effect.{ FiberIO, IO }

Expand All @@ -12,8 +14,9 @@ trait CatsUnsafeRun extends UnsafeRun[IO] with CatsUnsafeRunPlatformCompat {
override implicit val parallel = IO.parallelForIO
override implicit val effect = IO.asyncForIO

def cancel(token: CancelToken): Unit = sync(token.cancel)
def cancel(token: CancelToken): Unit = unsafeRunSync(token.cancel)

def async(task: IO[Unit]): Unit = task.unsafeRunAndForget()
def unsafeRunAndForget(task: IO[Unit]): Unit = task.unsafeRunAndForget()
def unsafeRunToFuture(task: IO[Unit]): Future[Unit] = task.unsafeToFuture()

}
6 changes: 6 additions & 0 deletions modules/core/src-native/org/junit/runner/RunWith.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.junit.runner

/**
* Stub used for cross-compilation
*/
class RunWith[T](cls: Class[T]) extends scala.annotation.StaticAnnotation
8 changes: 8 additions & 0 deletions modules/core/src-native/weaver/PlatformCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package weaver

private[weaver] object PlatformCompat {
val platform: Platform = Platform.Native

def getClassLoader(clazz: java.lang.Class[_]): ClassLoader =
new ClassLoader() {}
}
35 changes: 35 additions & 0 deletions modules/core/src-native/weaver/internals/Timestamp.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package weaver.internals

import scala.scalanative.posix
import scala.scalanative.unsafe._

import posix.time
import posix.timeOps._

private[weaver] object Timestamp {

def format(epochSecond: Long): String = Zone { implicit zone =>
val out = alloc[time.tm]()
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this can be stackalloc, no?

We're not return the pointer to the caller, so we don't need it on the heap, and the return value is a Scala String which will be on the heap anyways.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And this makes Zone unnecessary as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah fair enough, I copied it verbatim from 0.4.0 code I had laying around

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed aa7296e

val timePtr = alloc[time.time_t]()
!timePtr = epochSecond
val gmTime: Ptr[time.tm] = time.localtime_r(timePtr, out)
val hour = gmTime.tm_hour
val minutes = gmTime.tm_min
val seconds = gmTime.tm_sec
s"$hour:$minutes:$seconds"
}

def localTime(hours: Int, minutes: Int, seconds: Int): Long = Zone {
implicit zone =>
val out = alloc[time.tm]()
Copy link
Collaborator

Choose a reason for hiding this comment

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

same as above - the return is Long, by value, so the memory can be allocated by stackalloc - this would make it much, much faster as well

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed aa7296e

val timePtr = alloc[time.time_t]()
!timePtr = time.time(null)
val gmTime: Ptr[time.tm] = time.gmtime_r(timePtr, out)

gmTime.tm_hour = hours
gmTime.tm_min = minutes
gmTime.tm_sec = seconds
gmTime.tm_isdst = -1; // Is DST on? 1 = yes, 0 = no, -1 = unknown
time.mktime(gmTime).longValue()
}
}
6 changes: 6 additions & 0 deletions modules/core/src-native/weaver/junit/WeaverRunner.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package weaver.junit

/**
* Stub used for cross-compilation
*/
class WeaverRunner()
6 changes: 4 additions & 2 deletions modules/core/src/weaver/Platform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ sealed abstract class Platform(val name: String)
object Platform {
def isJVM: Boolean = PlatformCompat.platform == JVM
def isJS: Boolean = PlatformCompat.platform == JS
def isNative: Boolean = PlatformCompat.platform == Native
def isScala3: Boolean = ScalaCompat.isScala3

case object JS extends Platform("js")
case object JVM extends Platform("jvm")
case object JS extends Platform("js")
case object JVM extends Platform("jvm")
case object Native extends Platform("native")
}
6 changes: 4 additions & 2 deletions modules/core/src/weaver/UnsafeRun.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package weaver

import scala.concurrent.Future
import scala.concurrent.duration.FiniteDuration

import cats.Parallel
Expand Down Expand Up @@ -37,7 +38,8 @@ trait UnsafeRun[F[_]] extends EffectCompat[F] {
def background(task: F[Unit]): CancelToken
def cancel(token: CancelToken): Unit

def sync(task: F[Unit]): Unit
def async(task: F[Unit]): Unit
def unsafeRunSync(task: F[Unit]): Unit
def unsafeRunAndForget(task: F[Unit]): Unit
def unsafeRunToFuture(task: F[Unit]): Future[Unit]

}
3 changes: 1 addition & 2 deletions modules/core/src/weaver/suites.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ abstract class RunnableSuite[F[_]] extends EffectSuite[F] {
private[weaver] def getEffectCompat: UnsafeRun[EffectType] = effectCompat
def plan : List[TestName]
private[weaver] def runUnsafe(args: List[String])(report: TestOutcome => Unit) : Unit =
effectCompat.sync(run(args)(outcome => effectCompat.effect.delay(report(outcome))))
effectCompat.unsafeRunSync(run(args)(outcome => effectCompat.effect.delay(report(outcome))))
}

abstract class MutableFSuite[F[_]] extends RunnableSuite[F] {
Expand Down Expand Up @@ -164,4 +164,3 @@ abstract class FunSuiteF[F[_]] extends RunnableSuite[F] with FunSuiteAux { self
private[weaver] object initError extends AssertionError(
"Cannot define new tests after TestSuite was initialized"
)

10 changes: 8 additions & 2 deletions modules/core/zio/src/weaver/ziocompat/ZIOUnsafeRun.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package weaver
package ziocompat

import scala.concurrent.Future

import cats.Parallel
import cats.effect.Async

Expand All @@ -23,7 +25,11 @@ object ZIOUnsafeRun extends UnsafeRun[T] {
def cancel(token: Fiber.Id => Exit[Throwable, Unit]): Unit =
discard[Exit[Throwable, Unit]](token(Fiber.Id.None))

def sync(task: T[Unit]): Unit = runtime.unsafeRun(task)
def unsafeRunSync(task: T[Unit]): Unit = runtime.unsafeRun(task)

def unsafeRunAndForget(task: T[Unit]): Unit =
runtime.unsafeRunAsync(task)(_ => ())

def async(task: T[Unit]): Unit = runtime.unsafeRunAsync(task)(_ => ())
def unsafeRunToFuture(task: T[Unit]): Future[Unit] =
runtime.unsafeRunToFuture(task)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class CatsEffect(errorStream: PrintStream)
CatsFingerprints,
CatsUnsafeRun,
errorStream) {
def this() = this(System.err)
def this() = {
this(System.err)
}
}

object CatsFingerprints
Expand Down
11 changes: 11 additions & 0 deletions modules/framework/src-js-native/AsyncTask.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package weaver

import scala.concurrent.Future

import sbt.testing.{ EventHandler, Logger, Task }

private[weaver] trait AsyncTask extends Task {
def executeFuture(
eventHandler: EventHandler,
loggers: Array[Logger]): Future[Unit]
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ private[weaver] trait DogFoodCompat[F[_]] { self: DogFood[F] =>
logger: sbt.testing.Logger,
maxParallelism: Int)(tasks: List[sbt.testing.Task]): F[Unit] = {
tasks.traverse { task =>
self.framework.unsafeRun.async {
(cb: (Either[Throwable, Unit] => Unit)) =>
task.execute(eventHandler, Array(logger), _ => cb(Right(())))
self.framework.unsafeRun.fromFuture {
task.asInstanceOf[AsyncTask].executeFuture(eventHandler, Array(logger))
}
}.map { _ =>
Reporter.logRunFinished(Array(logger))(
Expand Down
Loading