summaryrefslogtreecommitdiff
path: root/scalanativelib/test
diff options
context:
space:
mode:
authorAndrew Richards <richards.aj@gmail.com>2018-07-18 08:50:09 +0100
committerLi Haoyi <haoyi.sg@gmail.com>2018-07-18 15:50:09 +0800
commit1829391c0de0efcb96b1187fe35a0e9127e00d29 (patch)
tree4216bde1516e75fccbc8a8c6a0d1eebb5b929364 /scalanativelib/test
parent2d779b8ccd0a2f29a7d14dc193b4ad093142b521 (diff)
downloadmill-1829391c0de0efcb96b1187fe35a0e9127e00d29.tar.gz
mill-1829391c0de0efcb96b1187fe35a0e9127e00d29.tar.bz2
mill-1829391c0de0efcb96b1187fe35a0e9127e00d29.zip
WIP: Scala native (#206)
* add scala-native PR#1143 as submodule * first pass at integrating scala-native build into mill including worker/bridge * add the native libraries to the compile and run classpath * sssshhh don't be so noisy * update scala-native to latest build WIP * update mill to latest scala-native build-api code * add test interface from scala-native this code is not published ornot published at the correct scala version so copy it in for now * implement tests for scala-native very messy at the moment also correct bridge version as much as possible with out a scala-native release * update to scala-native/master scala-native #1143 now merged * Remove scala-native submodule * updates for scala-native 0.3.7 release * fixes after rebase * make test framework agnostic and tidy dependencies * add robust method of getting JVM classpath for running tests support for multiple test frameworks tidy up * rebase fixes for 0.2.0 * add SbtNativeModule and tidy * rebase fixes * fix building of compile / run Classpath (via transitiveIvyDeps) better method of loading JVM test frameworks * add tests for build, run, utest, scalatest * move native tests into it own trait which can be extended/overidden * change release mode to a sealed trait instead of boolean * add logLevel to ScalaNativeModule and plumb in propagate release and log levels to test projects * use test-runner from scala-native instead of including project source add ability easily compile against scala-native snapshots * add some docs * update to 0.3.8
Diffstat (limited to 'scalanativelib/test')
-rw-r--r--scalanativelib/test/resources/hello-native-world/src/hello/ArgsParser.scala5
-rw-r--r--scalanativelib/test/resources/hello-native-world/src/hello/Main.scala6
-rw-r--r--scalanativelib/test/resources/hello-native-world/test/src/scalatest/ArgsParserSpec.scala21
-rw-r--r--scalanativelib/test/resources/hello-native-world/test/src/scalatest/MainSpec.scala18
-rw-r--r--scalanativelib/test/resources/hello-native-world/test/src/utest/tests/ArgsParserTests.scala24
-rw-r--r--scalanativelib/test/resources/hello-native-world/test/src/utest/tests/MainTests.scala23
-rw-r--r--scalanativelib/test/src/mill/scalanativelib/HelloNativeWorldTests.scala217
7 files changed, 314 insertions, 0 deletions
diff --git a/scalanativelib/test/resources/hello-native-world/src/hello/ArgsParser.scala b/scalanativelib/test/resources/hello-native-world/src/hello/ArgsParser.scala
new file mode 100644
index 00000000..8ad93598
--- /dev/null
+++ b/scalanativelib/test/resources/hello-native-world/src/hello/ArgsParser.scala
@@ -0,0 +1,5 @@
+package hello
+
+object ArgsParser {
+ def parse(s:String): Seq[String] = s.split(":").toSeq
+}
diff --git a/scalanativelib/test/resources/hello-native-world/src/hello/Main.scala b/scalanativelib/test/resources/hello-native-world/src/hello/Main.scala
new file mode 100644
index 00000000..5e04dbb3
--- /dev/null
+++ b/scalanativelib/test/resources/hello-native-world/src/hello/Main.scala
@@ -0,0 +1,6 @@
+package hello
+
+object Main extends App {
+ println("Hello " + vmName)
+ def vmName = sys.props("java.vm.name")
+}
diff --git a/scalanativelib/test/resources/hello-native-world/test/src/scalatest/ArgsParserSpec.scala b/scalanativelib/test/resources/hello-native-world/test/src/scalatest/ArgsParserSpec.scala
new file mode 100644
index 00000000..dd160989
--- /dev/null
+++ b/scalanativelib/test/resources/hello-native-world/test/src/scalatest/ArgsParserSpec.scala
@@ -0,0 +1,21 @@
+package hellotest
+
+import hello._
+import org.scalatest._
+
+class ArgsParserSpec extends FlatSpec with Matchers {
+
+ behavior of "ArgsParser"
+
+ "parse" should "one" in {
+ val result = ArgsParser.parse("hello:world")
+ result should have length 2
+ result should contain only ("hello", "world")
+ }
+
+ it should "two" in {
+ val result = ArgsParser.parse("hello:world")
+ result should have length 80
+ }
+
+}
diff --git a/scalanativelib/test/resources/hello-native-world/test/src/scalatest/MainSpec.scala b/scalanativelib/test/resources/hello-native-world/test/src/scalatest/MainSpec.scala
new file mode 100644
index 00000000..582c3692
--- /dev/null
+++ b/scalanativelib/test/resources/hello-native-world/test/src/scalatest/MainSpec.scala
@@ -0,0 +1,18 @@
+package hellotest
+
+import hello._
+import org.scalatest._
+
+class MainSpec extends FlatSpec with Matchers {
+
+ behavior of "Main"
+
+ "vmName" should "contain Native" in {
+ Main.vmName should include ("Native")
+ }
+
+ it should "contain Scala" in {
+ Main.vmName should include ("Scala")
+ }
+
+}
diff --git a/scalanativelib/test/resources/hello-native-world/test/src/utest/tests/ArgsParserTests.scala b/scalanativelib/test/resources/hello-native-world/test/src/utest/tests/ArgsParserTests.scala
new file mode 100644
index 00000000..7929f947
--- /dev/null
+++ b/scalanativelib/test/resources/hello-native-world/test/src/utest/tests/ArgsParserTests.scala
@@ -0,0 +1,24 @@
+package hellotest
+
+import hello._
+import utest._
+
+object ArgsParserTests extends TestSuite {
+
+ def tests: Tests = Tests {
+ 'one - {
+ val result = ArgsParser.parse("hello:world")
+ assert(
+ result.length == 2,
+ result == Seq("hello", "world")
+ )
+ }
+ 'two - { // we fail this test to check testing in scala.js
+ val result = ArgsParser.parse("hello:world")
+ assert(
+ result.length == 80
+ )
+ }
+ }
+
+}
diff --git a/scalanativelib/test/resources/hello-native-world/test/src/utest/tests/MainTests.scala b/scalanativelib/test/resources/hello-native-world/test/src/utest/tests/MainTests.scala
new file mode 100644
index 00000000..3a89f90c
--- /dev/null
+++ b/scalanativelib/test/resources/hello-native-world/test/src/utest/tests/MainTests.scala
@@ -0,0 +1,23 @@
+package hellotest
+
+import hello._
+import utest._
+
+object MainTests extends TestSuite {
+
+ def tests: Tests = Tests {
+ 'vmName - {
+ 'containNative - {
+ assert(
+ Main.vmName.contains("Native")
+ )
+ }
+ 'containScala - {
+ assert(
+ Main.vmName.contains("Scala")
+ )
+ }
+ }
+ }
+
+}
diff --git a/scalanativelib/test/src/mill/scalanativelib/HelloNativeWorldTests.scala b/scalanativelib/test/src/mill/scalanativelib/HelloNativeWorldTests.scala
new file mode 100644
index 00000000..4c67b98f
--- /dev/null
+++ b/scalanativelib/test/src/mill/scalanativelib/HelloNativeWorldTests.scala
@@ -0,0 +1,217 @@
+package mill.scalanativelib
+
+import java.util.jar.JarFile
+
+import ammonite.ops._
+import mill._
+import mill.define.Discover
+import mill.eval.{Evaluator, Result}
+import mill.scalalib.{CrossScalaModule, DepSyntax, Lib, PublishModule, TestRunner}
+import mill.scalalib.publish.{Developer, License, PomSettings, VersionControl}
+import mill.util.{TestEvaluator, TestUtil}
+import utest._
+
+
+import scala.collection.JavaConverters._
+
+
+object HelloNativeWorldTests extends TestSuite {
+ val workspacePath = TestUtil.getOutPathStatic() / "hello-native-world"
+
+ trait HelloNativeWorldModule extends CrossScalaModule with ScalaNativeModule with PublishModule {
+ override def millSourcePath = workspacePath
+ def publishVersion = "0.0.1-SNAPSHOT"
+ override def mainClass = Some("hello.Main")
+ }
+
+ object HelloNativeWorld extends TestUtil.BaseModule {
+ val matrix = for {
+ scala <- Seq("2.11.12")
+ scalaNative <- Seq("0.3.8")
+ mode <- List(ReleaseMode.Debug, ReleaseMode.Release)
+ } yield (scala, scalaNative, mode)
+
+ object helloNativeWorld extends Cross[BuildModule](matrix:_*)
+ class BuildModule(val crossScalaVersion: String, sNativeVersion: String, mode: ReleaseMode) extends HelloNativeWorldModule {
+ override def artifactName = "hello-native-world"
+ def scalaNativeVersion = sNativeVersion
+ def releaseMode = T{ mode }
+ def pomSettings = PomSettings(
+ organization = "com.lihaoyi",
+ description = "hello native world ready for real world publishing",
+ url = "https://github.com/lihaoyi/hello-world-publish",
+ licenses = Seq(License.Common.Apache2),
+ versionControl = VersionControl.github("lihaoyi", "hello-world-publish"),
+ developers =
+ Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
+ )
+ }
+
+ object buildUTest extends Cross[BuildModuleUtest](matrix:_*)
+ class BuildModuleUtest(crossScalaVersion: String, sNativeVersion: String, mode: ReleaseMode)
+ extends BuildModule(crossScalaVersion, sNativeVersion, mode) {
+ object test extends super.Tests {
+ override def sources = T.sources{ millSourcePath / 'src / 'utest }
+ def testFrameworks = Seq("utest.runner.Framework")
+ override def ivyDeps = Agg(
+ ivy"com.lihaoyi::utest::0.6.4"
+ )
+ }
+ }
+
+ object buildScalaTest extends Cross[BuildModuleScalaTest](matrix:_*)
+ class BuildModuleScalaTest(crossScalaVersion: String, sNativeVersion: String, mode: ReleaseMode)
+ extends BuildModule(crossScalaVersion, sNativeVersion, mode) {
+ object test extends super.Tests {
+ override def sources = T.sources{ millSourcePath / 'src / 'scalatest }
+ def testFrameworks = Seq("org.scalatest.tools.Framework")
+ override def ivyDeps = Agg(
+ ivy"org.scalatest::scalatest::3.2.0-SNAP10"
+ )
+ }
+ }
+ override lazy val millDiscover = Discover[this.type]
+ }
+
+ val millSourcePath = pwd / 'scalanativelib / 'test / 'resources / "hello-native-world"
+
+ val helloWorldEvaluator = TestEvaluator.static(HelloNativeWorld)
+
+
+ val mainObject = helloWorldEvaluator.outPath / 'src / "Main.scala"
+
+ def tests: Tests = Tests {
+ prepareWorkspace()
+ 'compile - {
+ def testCompileFromScratch(scalaVersion: String,
+ scalaNativeVersion: String,
+ mode: ReleaseMode): Unit = {
+ val Right((result, evalCount)) =
+ helloWorldEvaluator(HelloNativeWorld.helloNativeWorld(scalaVersion, scalaNativeVersion, mode).compile)
+
+ val outPath = result.classes.path
+ val outputFiles = ls.rec(outPath).filter(_.isFile)
+ val expectedClassfiles = compileClassfiles(outPath / 'hello)
+ assert(
+ outputFiles.toSet == expectedClassfiles,
+ evalCount > 0
+ )
+
+ // don't recompile if nothing changed
+ val Right((_, unchangedEvalCount)) =
+ helloWorldEvaluator(HelloNativeWorld.helloNativeWorld(scalaVersion, scalaNativeVersion, mode).compile)
+ assert(unchangedEvalCount == 0)
+ }
+
+ 'fromScratch_21112_037 - testCompileFromScratch("2.11.12", "0.3.8", ReleaseMode.Debug)
+ }
+
+ 'jar - {
+ 'containsNirs - {
+ val Right((result, evalCount)) =
+ helloWorldEvaluator(HelloNativeWorld.helloNativeWorld("2.11.12", "0.3.8", ReleaseMode.Debug).jar)
+ val jar = result.path
+ val entries = new JarFile(jar.toIO).entries().asScala.map(_.getName)
+ assert(entries.contains("hello/Main$.nir"))
+ }
+ }
+ 'publish - {
+ def testArtifactId(scalaVersion: String,
+ scalaNativeVersion: String,
+ mode: ReleaseMode,
+ artifactId: String): Unit = {
+ val Right((result, evalCount)) = helloWorldEvaluator(
+ HelloNativeWorld.helloNativeWorld(scalaVersion, scalaNativeVersion, mode: ReleaseMode).artifactMetadata)
+ assert(result.id == artifactId)
+ }
+ 'artifactId_038 - testArtifactId("2.11.12", "0.3.8", ReleaseMode.Debug, "hello-native-world_native0.3_2.11")
+ }
+ 'test - {
+ def runTests(testTask: define.Command[(String, Seq[TestRunner.Result])]): Map[String, Map[String, TestRunner.Result]] = {
+ val Left(Result.Failure(_, Some(res))) = helloWorldEvaluator(testTask)
+
+ val (doneMsg, testResults) = res
+ testResults
+ .groupBy(_.fullyQualifiedName)
+ .mapValues(_.map(e => e.selector -> e).toMap)
+ }
+
+ def checkUtest(scalaVersion: String, scalaNativeVersion: String, mode: ReleaseMode) = {
+ val resultMap = runTests(HelloNativeWorld.buildUTest(scalaVersion, scalaNativeVersion, mode).test.test())
+
+ val mainTests = resultMap("hellotest.MainTests")
+ val argParserTests = resultMap("hellotest.ArgsParserTests")
+
+ assert(
+ mainTests.size == 2,
+ mainTests("hellotest.MainTests.vmName.containNative").status == "Success",
+ mainTests("hellotest.MainTests.vmName.containScala").status == "Success",
+
+ argParserTests.size == 2,
+ argParserTests("hellotest.ArgsParserTests.one").status == "Success",
+ argParserTests("hellotest.ArgsParserTests.two").status == "Failure"
+ )
+ }
+
+ def checkScalaTest(scalaVersion: String, scalaNativeVersion: String, mode: ReleaseMode) = {
+ val resultMap = runTests(HelloNativeWorld.buildScalaTest(scalaVersion, scalaNativeVersion, mode).test.test())
+
+ val mainSpec = resultMap("hellotest.MainSpec")
+ val argParserSpec = resultMap("hellotest.ArgsParserSpec")
+
+ assert(
+ mainSpec.size == 2,
+ mainSpec("vmName should contain Native").status == "Success",
+ mainSpec("vmName should contain Scala").status == "Success",
+
+ argParserSpec.size == 2,
+ argParserSpec("parse should one").status == "Success",
+ argParserSpec("parse should two").status == "Failure"
+ )
+ }
+
+ 'utest_21112_038_debug - (checkUtest("2.11.12", "0.3.8", ReleaseMode.Debug))
+ 'utest_21112_038_release - (checkUtest("2.11.12", "0.3.8", ReleaseMode.Release))
+ 'scalaTest_21112_038_debug - (checkScalaTest("2.11.12", "0.3.8", ReleaseMode.Debug))
+ 'scalaTest_21112_038_release - (checkScalaTest("2.11.12", "0.3.8", ReleaseMode.Release))
+ }
+
+ def checkRun(scalaVersion: String, scalaNativeVersion: String, mode: ReleaseMode): Unit = {
+ val task = HelloNativeWorld.helloNativeWorld(scalaVersion, scalaNativeVersion, mode).run()
+
+ val Right((_, evalCount)) = helloWorldEvaluator(task)
+
+ val paths = Evaluator.resolveDestPaths(
+ helloWorldEvaluator.outPath,
+ task.ctx.segments
+ )
+ val log = read(paths.log)
+ assert(
+ evalCount > 0,
+ log.contains("Scala Native")
+ )
+ }
+
+ 'run - {
+ 'run_21112_038_debug - (checkRun("2.11.12", "0.3.8", ReleaseMode.Debug))
+ 'run_21112_038_release - (checkRun("2.11.12", "0.3.8", ReleaseMode.Release))
+ }
+ }
+
+ def compileClassfiles(parentDir: Path) = Set(
+ parentDir / "ArgsParser$.class",
+ parentDir / "ArgsParser$.nir",
+ parentDir / "ArgsParser.class",
+ parentDir / "Main.class",
+ parentDir / "Main$.class",
+ parentDir / "Main$delayedInit$body.class",
+ parentDir / "Main$.nir",
+ parentDir / "Main$delayedInit$body.nir"
+ )
+
+ def prepareWorkspace(): Unit = {
+ rm(workspacePath)
+ mkdir(workspacePath / up)
+ cp(millSourcePath, workspacePath)
+ }
+}