summaryrefslogblamecommitdiff
path: root/scalanativelib/test/src/mill/scalanativelib/HelloNativeWorldTests.scala
blob: 4c67b98fb83ba4d6b3343dd4e8a2590aa3b90f3e (plain) (tree)
























































































































































































































                                                                                                                                
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)
  }
}