org.specs2.specification.ExecutingSpecification.scala Maven / Gradle / Ivy
package org.specs2
package specification
import collection.Iterablex._
import java.util.concurrent.{Executors, ExecutorService}
import control.NamedThreadFactory
import ExecutingSpecification._
import main.Arguments
import scalaz.EphemeralStream._
/**
* a specification with a name and a sequence of fragments being executed
*/
case class ExecutingSpecification(name: SpecName, arguments: Arguments, fs: Seq[ExecutingFragment], executor: ExecutorService) {
/** @return the executed fragments, but as a lazy list */
lazy val execute = ExecutedSpecification(name, foreach { (n, fs) => fs.view.toSeq }.map(_.get))
/** @return the executed fragments */
def executed = execute
/** @return a lazy list where each fragment will be executed on access */
def foreach[T](f: (SpecName, Seq[ExecutingFragment]) => T) =
try { f(name, fs.view) } finally { terminate() }
/** @return an ExecutingSpecification where each executed fragment is mapped to another one */
def map(f: ExecutedFragment => ExecutedFragment) = copy(fs = fs.map(_.map(f)))
override def toString = fs.mkString("\n")
def terminate() = executor.shutdown()
}
/**
* for testing only
*/
private[specs2]
object ExecutingSpecification {
/**
* @return an ExecutedSpecification from a sequence of already executed fragments
* this method is only for testing as it returns incorrect finished executing fragments (with a wrong "original" value)
*/
def create(fs: Seq[ExecutedFragment], args: Arguments): ExecutingSpecification =
apply(fs.map(FinishedExecutingFragment), args)
/**
* @return an ExecutedSpecification from a sequence of already executed fragments
*/
def create(name: SpecName, fs: Seq[ExecutedFragment], args: Arguments = Arguments()): ExecutingSpecification =
ExecutingSpecification(name, args, fs.map(FinishedExecutingFragment), newExecutor)
/**
* @return an ExecutedSpecification from a sequence of fragments being executed
*/
def apply(fs: Seq[ExecutingFragment], args: Arguments): ExecutingSpecification = {
fs.map(_.original) match {
case (s: SpecStart) +: rest => ExecutingSpecification(s.specName, args, fs, newExecutor)
case other => ExecutingSpecification(SpecName(""), args, fs, newExecutor)
}
}
private def newExecutor = {
Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors, new NamedThreadFactory("specs2.DefaultExecutionStrategy"))
}
}