minitest.runner.Task.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2014-2019 by The Minitest Project Developers.
* Some rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package minitest.runner
import org.portablescala.reflect.Reflect
import minitest.api._
import sbt.testing.{Task => BaseTask, _}
import scala.compat.Platform.EOL
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future, Promise}
import scala.util.Try
private object Task {
private def loadModule(name: String, loader: ClassLoader): Any = {
Reflect
.lookupLoadableModuleClass(name + "$", loader)
.getOrElse(throw new ClassNotFoundException(name))
.loadModule()
}
}
final class Task(task: TaskDef, cl: ClassLoader) extends BaseTask {
implicit val ec: ExecutionContext = DefaultExecutionContext
def tags(): Array[String] = Array.empty
def taskDef(): TaskDef = task
def reportStart(name: String, loggers: Array[Logger]): Unit = {
for (logger <- loggers) {
val withColors = logger.ansiCodesSupported()
val color = if (withColors) Console.GREEN else ""
val reset = if (withColors) Console.RESET else ""
logger.info(color + name + reset + EOL)
}
}
def report(name: String, r: Result[_], loggers: Array[Logger]): Unit = {
for (logger <- loggers) {
logger.info(r.formatted(name, logger.ansiCodesSupported()))
}
}
def execute(eventHandler: EventHandler, loggers: Array[Logger],
continuation: Array[BaseTask] => Unit): Unit = {
def loop(props: Iterator[TestSpec[Unit, Unit]]): Future[Unit] = {
if (!props.hasNext) unit else {
val property = props.next()
val startTS = System.currentTimeMillis()
val futureResult = property(())
futureResult.flatMap { result =>
val endTS = System.currentTimeMillis()
report(property.name, result, loggers)
eventHandler.handle(event(result, endTS - startTS))
loop(props)
}
}
}
val future = loadSuite(task.fullyQualifiedName(), cl).fold(unit) { suite =>
reportStart(task.fullyQualifiedName(), loggers)
suite.properties.setupSuite()
loop(suite.properties.iterator).map { _ =>
suite.properties.tearDownSuite()
}
}
future.onComplete(_ => continuation(Array.empty))
}
def execute(eventHandler: EventHandler, loggers: Array[Logger]): Array[BaseTask] = {
val p = Promise[Unit]()
execute(eventHandler, loggers, _ => p.success(()))
Await.result(p.future, Duration.Inf)
Array.empty
}
def loadSuite(name: String, loader: ClassLoader): Option[AbstractTestSuite] = {
Try(Task.loadModule(name, loader)).toOption
.collect { case ref: AbstractTestSuite => ref }
}
def event(result: Result[Unit], durationMillis: Long): Event = new Event {
def fullyQualifiedName(): String =
task.fullyQualifiedName()
def throwable(): OptionalThrowable =
result match {
case Result.Exception(source, _) =>
new OptionalThrowable(source)
case Result.Failure(_, Some(source), _) =>
new OptionalThrowable(source)
case _ =>
new OptionalThrowable()
}
def status(): Status =
result match {
case Result.Exception(_,_) =>
Status.Error
case Result.Failure(_,_,_) =>
Status.Failure
case Result.Success(_) =>
Status.Success
case Result.Ignored(_,_) =>
Status.Ignored
case Result.Canceled(_,_) =>
Status.Canceled
}
def selector(): Selector = {
task.selectors().head
}
def fingerprint(): Fingerprint =
task.fingerprint()
def duration(): Long =
durationMillis
}
private[this] val unit = Future.successful(())
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy