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

Cross compile to Scala Native #114

Merged
merged 1 commit into from Jun 25, 2017
Merged
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
22 changes: 16 additions & 6 deletions .travis.yml
@@ -1,17 +1,27 @@
language: scala
sudo: false
sudo: required
dist: trusty

jdk:
- oraclejdk8
scala:
- 2.10.6
- 2.11.11
- 2.12.2
- 2.13.0-M1

matrix:
include:
- scala: 2.10.6
jdk: openjdk7
script: sbt ++$TRAVIS_SCALA_VERSION utestJVM/test utestJS/test

- scala: 2.11.11
before_script:
- curl https://raw.githubusercontent.com/scala-native/scala-native/v0.3.0/bin/travis_setup.sh | bash -x
sudo: required
script: sbt ++$TRAVIS_SCALA_VERSION utestJVM/test utestJS/test utestNative/test

- scala: 2.12.2
script: sbt ++$TRAVIS_SCALA_VERSION utestJVM/test utestJS/test

- scala: 2.13.0-M1
script: sbt ++$TRAVIS_SCALA_VERSION utestJVM/test utestJS/test

# Taken from https://github.com/typelevel/cats/blob/master/.travis.yml
before_cache:
Expand Down
13 changes: 11 additions & 2 deletions build.sbt
@@ -1,3 +1,4 @@
import sbtcrossproject.{crossProject, CrossType}
import com.typesafe.sbt.pgp.PgpKeys._

name in ThisBuild := "utest"
Expand All @@ -10,8 +11,9 @@ triggeredMessage in ThisBuild := Watched.clearWhenTriggered
releaseTagComment in ThisBuild := s"v${(version in ThisBuild).value}"
releaseVcsSign in ThisBuild := true

lazy val utest = crossProject
lazy val utest = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.settings(
name := "utest",
scalacOptions := Seq("-Ywarn-dead-code"),
scalacOptions in Test -= "-Ywarn-dead-code",
libraryDependencies ++= macroDependencies(scalaVersion.value),
Expand Down Expand Up @@ -61,6 +63,12 @@ lazy val utest = crossProject
),
resolvers += Resolver.sonatypeRepo("snapshots")
)
.nativeSettings(
scalaVersion := "2.11.11",
libraryDependencies ++= Seq(
"org.scala-native" %%% "test-interface" % "0.3.0"
)
)

def macroDependencies(version: String) =
("org.scala-lang" % "scala-reflect" % version) +:
Expand All @@ -72,9 +80,10 @@ def macroDependencies(version: String) =

lazy val utestJS = utest.js
lazy val utestJVM = utest.jvm
lazy val utestNative = utest.native

lazy val root = project.in(file("."))
.aggregate(utestJS, utestJVM)
.aggregate(utestJS, utestJVM, utestNative)
.settings(
publishTo := Some(Resolver.file("Unused transient repository", target.value / "fakepublish")),
publishArtifact := false,
Expand Down
10 changes: 6 additions & 4 deletions project/plugins.sbt
@@ -1,4 +1,6 @@
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.16")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.1")
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.5")

addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.1")
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.5")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.16")
addSbtPlugin("org.scala-native" % "sbt-crossproject" % "0.2.0")
addSbtPlugin("org.scala-native" % "sbt-scalajs-crossproject" % "0.2.0")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.3.0")
19 changes: 19 additions & 0 deletions utest/native/PlatformShims.scala
@@ -0,0 +1,19 @@
package utest

// Taken from the implementation for JS

import scala.concurrent.Future

/**
* Platform specific stuff that differs between JVM and Native
*/
object PlatformShims {
def await[T](f: Future[T]): T = {
f.value match {
case Some(v) => v.get
case None => throw new IllegalStateException(
"Test that returns Future must be run asynchronously in Scala Native, see TestTreeSeq::runAsync"
)
}
}
}
16 changes: 16 additions & 0 deletions utest/native/src/test/scala/utest/Scheduler.scala
@@ -0,0 +1,16 @@
package utest

import scala.concurrent.{ ExecutionContext, Future }
import scala.concurrent.duration.FiniteDuration

object Scheduler {
// Will execute immediately, because we cannot currenly schedule
// computation in Scala Native. (Execution happens either immediately
// or at the end of the program.)
def scheduleOnce[T](interval: FiniteDuration)
(thunk: => T)
(implicit executor: ExecutionContext): Unit = {
Future { thunk }
()
}
}
18 changes: 8 additions & 10 deletions utest/shared/src/test/scala/test/utest/AssertsTests.scala
Expand Up @@ -53,14 +53,12 @@ object AssertsTests extends utest.TestSuite{
)
}
'failureWithException{
val x = 1L
val y = 0l
try {
assert(x / y == 10)
assert(Iterator.empty.next() == 10)
Predef.assert(false)
} catch {case e @ utest.AssertionError(src, logged, cause) =>
Predef.assert(cause.isInstanceOf[ArithmeticException])
Predef.assert(cause.getMessage == "/ by zero")
Predef.assert(cause.isInstanceOf[NoSuchElementException])
Predef.assert(cause.getMessage == "next on empty iterator")
e.getMessage
}
}
Expand Down Expand Up @@ -178,14 +176,14 @@ object AssertsTests extends utest.TestSuite{

'failureWithException{
try {
val a = 1L
val a = Iterator.empty
val b = 2
assertMatch(Seq(a / 0, 3, b)){case Seq(1, 2) =>}
assertMatch(Seq(a.next(), 3, b)){case Seq(1, 2) =>}
Predef.assert(false)
} catch{ case e: utest.AssertionError =>
Predef.assert(e.captured == Seq(TestValue("a", "Long", 1)))
Predef.assert(e.cause.isInstanceOf[ArithmeticException])
Predef.assert(e.msg.contains("assertMatch(Seq(a / 0, 3, b)){case Seq(1, 2) =>}"))
Predef.assert(e.captured == Seq(TestValue("a", "Iterator[Nothing]", Iterator.empty)))
Predef.assert(e.cause.isInstanceOf[NoSuchElementException])
Predef.assert(e.msg.contains("assertMatch(Seq(a.next(), 3, b)){case Seq(1, 2) =>}"))
e.getMessage
}
}
Expand Down
17 changes: 15 additions & 2 deletions utest/shared/src/test/scala/test/utest/FrameworkAsyncTests.scala
Expand Up @@ -4,6 +4,7 @@ import scala.concurrent.Future
import concurrent.duration._
object FrameworkAsyncTests extends utest.TestSuite{
implicit val ec = utest.framework.ExecutionContext.RunNow
private val isNative = sys.props("java.vm.name") == "Scala Native"

def tests = this{
'hello{
Expand All @@ -15,13 +16,23 @@ object FrameworkAsyncTests extends utest.TestSuite{
"testSuccessAsync" - {
val p = concurrent.Promise[Int]
utest.Scheduler.scheduleOnce(2 seconds)(p.success(123))
assert(!p.isCompleted)

// Not supported by Scala Native at the moment.
// Futures are completed either at the end of the `main` function or immediately.
// uTest will either consider that the test never completed, or too soon.
assert(isNative || !p.isCompleted)

p.future
}
"testFailAsync" - {
val p = concurrent.Promise[Int]
utest.Scheduler.scheduleOnce(2 seconds)(p.failure(new Exception("Boom")))
assert(!p.isCompleted)

// Not supported by Scala Native at the moment.
// Futures are completed either at the end of the `main` function or immediately.
// uTest will either consider that the test never completed, or too soon.
assert(isNative || !p.isCompleted)

p.future
}
"testSuccess" - {
Expand All @@ -48,6 +59,8 @@ object FrameworkAsyncTests extends utest.TestSuite{
"testCastError" - {
// These are Fatal in Scala.JS. Ensure they're handled else they freeze SBT.
Future {
// This test is disabled until scala-native/scala-native#858 is not fixed.
assert(!isNative)
0.asInstanceOf[String]
}
}
Expand Down
7 changes: 6 additions & 1 deletion utest/shared/src/test/scala/test/utest/FrameworkTests.scala
Expand Up @@ -219,7 +219,12 @@ object FrameworkTests extends utest.TestSuite{
// These are Fatal in Scala.JS. Ensure they're handled else they freeze SBT.
'catchCastError{
val tests = this{
'ah {0.asInstanceOf[String]}
'ah {
// This test is disabled until scala-native/scala-native#858 is not fixed.
val isNative = sys.props("java.vm.name") == "Scala Native"
assert(!isNative)
0.asInstanceOf[String]
}
}
assertMatch(tests.run(testPath=Seq("ah")).toSeq)
{case Seq(Result("ah", Failure(_), _))=>}
Expand Down