summaryrefslogblamecommitdiff
path: root/examples/scala-js/partest/src/main/scala/scala/tools/partest/scalajs/ScalaJSPartest.scala
blob: edd0ea90a8726411f44774164e99253c49b15f32 (plain) (tree)










































































































































































































                                                                                          
/* NSC -- new Scala compiler
 * Copyright 2005-2013 LAMP/EPFL
 * @author  Sébastien Doeraene
 */

package scala.tools.partest
package scalajs

import nest._
import Path._

import scala.tools.nsc.{ Global, Settings }
import scala.tools.nsc.reporters.{ Reporter }
import scala.tools.nsc.plugins.Plugin

import scala.scalajs.compiler.ScalaJSPlugin

import scala.io.Source

import sbt.testing.{ EventHandler, Logger, Fingerprint }
import java.io.File
import java.net.URLClassLoader

trait ScalaJSDirectCompiler extends DirectCompiler {
  override def newGlobal(settings: Settings, reporter: Reporter): PartestGlobal = {
    new PartestGlobal(settings, reporter) {
      override protected def loadRoughPluginsList(): List[Plugin] = {
        (super.loadRoughPluginsList() :+
            Plugin.instantiate(classOf[ScalaJSPlugin], this))
      }
    }
  }
}

class ScalaJSRunner(testFile: File, suiteRunner: SuiteRunner,
    scalaJSOverridePath: String, options: ScalaJSPartestOptions,
    noWarnFile: File) extends nest.Runner(testFile, suiteRunner) {

  private val compliantSems: List[String] = {
    scalaJSConfigFile("sem").fold(List.empty[String]) { file =>
      Source.fromFile(file).getLines.toList
    }
  }

  override val checkFile: File = {
    scalaJSConfigFile("check") getOrElse {
      // this is super.checkFile, but apparently we can't do that
      new FileOps(testFile).changeExtension("check")
    }
  }

  private def scalaJSConfigFile(ext: String): Option[File] = {
    val overrideFile = s"$scalaJSOverridePath/$kind/$fileBase.$ext"
    val url = getClass.getResource(overrideFile)
    Option(url).map(url => new File(url.toURI))
  }

  override def newCompiler = new DirectCompiler(this) with ScalaJSDirectCompiler
  override def extraJavaOptions = {
    super.extraJavaOptions ++ Seq(
        s"-Dscalajs.partest.noWarnFile=${noWarnFile.getAbsolutePath}",
        s"-Dscalajs.partest.optMode=${options.optMode.id}",
        s"-Dscalajs.partest.compliantSems=${compliantSems.mkString(",")}"
    )
  }
}

trait ScalaJSSuiteRunner extends SuiteRunner {

  // Stuff to mix in

  val options: ScalaJSPartestOptions

  /** Full scala version name. Used to discover blacklist (etc.) files */
  val scalaVersion: String

  // Stuff we provide

  override def banner: String = {
    import scala.scalajs.ir.ScalaJSVersions.{ current => currentVersion }

    super.banner.trim + s"""
    |Scala.js version is: $currentVersion
    |Scala.js options are:
    |optimizer:           ${options.optMode.shortStr}
    |testFilter:          ${options.testFilter.descr}
    """.stripMargin
  }

  override def runTest(testFile: File): TestState = {
    // Mostly copy-pasted from SuiteRunner.runTest(), unfortunately :-(
    val runner = new ScalaJSRunner(testFile, this, listDir, options, noWarnFile)

    // when option "--failed" is provided execute test only if log
    // is present (which means it failed before)
    val state =
      if (failed && !runner.logFile.canRead)
        runner.genPass()
      else {
        val (state, elapsed) =
          try timed(runner.run())
          catch {
            case t: Throwable => throw new RuntimeException(s"Error running $testFile", t)
          }
        NestUI.reportTest(state)
        runner.cleanup()
        state
      }
    onFinishTest(testFile, state)
  }

  override def runTestsForFiles(kindFiles: Array[File],
      kind: String): Array[TestState] = {
    super.runTestsForFiles(kindFiles.filter(shouldUseTest), kind)
  }

  private lazy val listDir =
    s"/scala/tools/partest/scalajs/$scalaVersion"

  private lazy val buglistedTestFileNames =
    readTestList(s"$listDir/BuglistedTests.txt")

  private lazy val blacklistedTestFileNames =
    readTestList(s"$listDir/BlacklistedTests.txt")

  private lazy val whitelistedTestFileNames =
    readTestList(s"$listDir/WhitelistedTests.txt")

  private lazy val noWarnFile: File = {
    val url = getClass.getResource(s"$listDir/NoDCEWarn.txt")
    assert(url != null, "Need NoDCEWarn.txt file")
    new File(url.toURI).getAbsolutePath()
  }

  private def readTestList(resourceName: String): Set[String] = {
    val source = scala.io.Source.fromURL(getClass.getResource(resourceName))

    val fileNames = for {
      line <- source.getLines
      trimmed = line.trim
      if trimmed != "" && !trimmed.startsWith("#")
    } yield extendShortTestName(trimmed)

    fileNames.toSet
  }

  private def extendShortTestName(testName: String) = {
    val srcDir = PathSettings.srcDir
    (srcDir / testName).toCanonical.getAbsolutePath
  }

  private lazy val testFilter: String => Boolean = {
    import ScalaJSPartestOptions._
    options.testFilter match {
      case UnknownTests => { absPath =>
        !blacklistedTestFileNames.contains(absPath) &&
        !whitelistedTestFileNames.contains(absPath) &&
        !buglistedTestFileNames.contains(absPath)
      }
      case BlacklistedTests => blacklistedTestFileNames
      case BuglistedTests   => buglistedTestFileNames
      case WhitelistedTests => whitelistedTestFileNames
      case SomeTests(names) => names.map(extendShortTestName _).toSet
    }
  }

  private def shouldUseTest(testFile: File): Boolean = {
    val absPath = testFile.toCanonical.getAbsolutePath
    testFilter(absPath)
  }
}

/* Pre-mixin ScalaJSSuiteRunner in SBTRunner, because this is looked up
 * via reflection from the sbt partest interface of Scala.js
 */
class ScalaJSSBTRunner(
    partestFingerprint: Fingerprint,
    eventHandler: EventHandler,
    loggers: Array[Logger],
    testRoot: File,
    testClassLoader: URLClassLoader,
    javaCmd: File,
    javacCmd: File,
    scalacArgs: Array[String],
    val options: ScalaJSPartestOptions,
    val scalaVersion: String
) extends SBTRunner(
    partestFingerprint, eventHandler, loggers, "test/files", testClassLoader,
    javaCmd, javacCmd, scalacArgs
) with ScalaJSSuiteRunner {

  // The test root for partest is read out through the system properties,
  // not passed as an argument
  sys.props("partest.root") = testRoot.getAbsolutePath()

  // Partests take at least 5h. We double, just to be sure. (default is 4 hours)
  sys.props("partest.timeout") = "10 hours"

  // Set showDiff on global UI module
  if (options.showDiff)
    NestUI.setDiffOnFail()

}