mirror of https://github.com/sbt/sbt.git
Merge pull request #3066 from eed3si9n/wip/testing
[sbt 1.0] Proof-of-concept testing events
This commit is contained in:
commit
40f6c4d01b
|
|
@ -14,4 +14,5 @@ Migration notes
|
|||
- Log options `-error`, `-warn`, `-info`, `-debug` are added as shorthand for `"early(error)"` etc.
|
||||
- `sbt.Process` and `sbt.ProcessExtra` are gone. Use `scala.sys.process` instead.
|
||||
- `incOptions.value.withNameHashing(...)` option is removed.
|
||||
- `TestResult.Value` is now `TestResult`.
|
||||
- the scripted plugin is cross-versioned now, so you must use %% when depending on it
|
||||
|
|
|
|||
|
|
@ -101,11 +101,14 @@ lazy val bundledLauncherProj =
|
|||
|
||||
// Runner for uniform test interface
|
||||
lazy val testingProj = (project in file("testing")).
|
||||
enablePlugins(ContrabandPlugin, JsonCodecPlugin).
|
||||
dependsOn(testAgentProj).
|
||||
settings(
|
||||
baseSettings,
|
||||
name := "Testing",
|
||||
libraryDependencies ++= Seq(testInterface,launcherInterface)
|
||||
libraryDependencies ++= Seq(testInterface,launcherInterface, sjsonNewScalaJson),
|
||||
sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-scala",
|
||||
contrabandFormatsForType in generateContrabands in Compile := ContrabandConfig.getFormats
|
||||
).
|
||||
configure(addSbtIO, addSbtCompilerClasspath, addSbtUtilLogging)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import Tests.{ Output => TestOutput, _ }
|
|||
import sbt.io.IO
|
||||
import sbt.util.Logger
|
||||
import sbt.ConcurrentRestrictions.Tag
|
||||
import sbt.protocol.testing._
|
||||
|
||||
private[sbt] object ForkTests {
|
||||
def apply(runners: Map[TestFramework, Runner], tests: List[TestDefinition], config: Execution, classpath: Seq[File], fork: ForkOptions, log: Logger, tag: Tag): Task[TestOutput] = {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package sbt
|
|||
|
||||
import sbt.Tests.{ Output, Summary }
|
||||
import sbt.util.{ Level, Logger }
|
||||
import sbt.protocol.testing.TestResult
|
||||
|
||||
/**
|
||||
* Logs information about tests after they finish.
|
||||
|
|
@ -138,7 +139,7 @@ object TestResultLogger {
|
|||
})
|
||||
|
||||
val printFailures = TestResultLogger((log, results, _) => {
|
||||
def select(resultTpe: TestResult.Value) = results.events collect {
|
||||
def select(resultTpe: TestResult) = results.events collect {
|
||||
case (name, tpe) if tpe.result == resultTpe =>
|
||||
scala.reflect.NameTransformer.decode(name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ import ConcurrentRestrictions.Tag
|
|||
import testing.{ AnnotatedFingerprint, Fingerprint, Framework, SubclassFingerprint, Runner, TaskDef, SuiteSelector, Task => TestTask }
|
||||
import scala.annotation.tailrec
|
||||
|
||||
import sbt.internal.util.ManagedLogger
|
||||
import sbt.util.Logger
|
||||
import sbt.protocol.testing.TestResult
|
||||
|
||||
sealed trait TestOption
|
||||
object Tests {
|
||||
|
|
@ -26,7 +28,7 @@ object Tests {
|
|||
* @param events The result of each test group (suite) executed during this test run.
|
||||
* @param summaries Explicit summaries directly provided by test frameworks. This may be empty, in which case a default summary will be generated.
|
||||
*/
|
||||
final case class Output(overall: TestResult.Value, events: Map[String, SuiteResult], summaries: Iterable[Summary])
|
||||
final case class Output(overall: TestResult, events: Map[String, SuiteResult], summaries: Iterable[Summary])
|
||||
|
||||
/**
|
||||
* Summarizes a test run.
|
||||
|
|
@ -162,7 +164,7 @@ object Tests {
|
|||
in.filter(t => seen.add(f(t)))
|
||||
}
|
||||
|
||||
def apply(frameworks: Map[TestFramework, Framework], testLoader: ClassLoader, runners: Map[TestFramework, Runner], discovered: Seq[TestDefinition], config: Execution, log: Logger): Task[Output] =
|
||||
def apply(frameworks: Map[TestFramework, Framework], testLoader: ClassLoader, runners: Map[TestFramework, Runner], discovered: Seq[TestDefinition], config: Execution, log: ManagedLogger): Task[Output] =
|
||||
{
|
||||
val o = processOptions(config, discovered, log)
|
||||
testTask(testLoader, frameworks, runners, o.tests, o.setup, o.cleanup, log, o.testListeners, config)
|
||||
|
|
@ -170,7 +172,7 @@ object Tests {
|
|||
|
||||
def testTask(loader: ClassLoader, frameworks: Map[TestFramework, Framework], runners: Map[TestFramework, Runner], tests: Seq[TestDefinition],
|
||||
userSetup: Iterable[ClassLoader => Unit], userCleanup: Iterable[ClassLoader => Unit],
|
||||
log: Logger, testListeners: Seq[TestReportListener], config: Execution): Task[Output] =
|
||||
log: ManagedLogger, testListeners: Seq[TestReportListener], config: Execution): Task[Output] =
|
||||
{
|
||||
def fj(actions: Iterable[() => Unit]): Task[Unit] = nop.dependsOn(actions.toSeq.fork(_()): _*)
|
||||
def partApp(actions: Iterable[ClassLoader => Unit]) = actions.toSeq map { a => () => a(loader) }
|
||||
|
|
@ -249,12 +251,20 @@ object Tests {
|
|||
|
||||
def processResults(results: Iterable[(String, SuiteResult)]): Output =
|
||||
Output(overall(results.map(_._2.result)), results.toMap, Iterable.empty)
|
||||
|
||||
private def severity(r: TestResult): Int =
|
||||
r match {
|
||||
case TestResult.Passed => 0
|
||||
case TestResult.Failed => 1
|
||||
case TestResult.Error => 2
|
||||
}
|
||||
|
||||
def foldTasks(results: Seq[Task[Output]], parallel: Boolean): Task[Output] =
|
||||
if (results.isEmpty)
|
||||
task { Output(TestResult.Passed, Map.empty, Nil) }
|
||||
else if (parallel)
|
||||
reduced(results.toIndexedSeq, {
|
||||
case (Output(v1, m1, _), Output(v2, m2, _)) => Output(if (v1.id < v2.id) v2 else v1, m1 ++ m2, Iterable.empty)
|
||||
case (Output(v1, m1, _), Output(v2, m2, _)) => Output(if (severity(v1) < severity(v2)) v2 else v1, m1 ++ m2, Iterable.empty)
|
||||
})
|
||||
else {
|
||||
def sequence(tasks: List[Task[Output]], acc: List[Output]): Task[List[Output]] = tasks match {
|
||||
|
|
@ -266,8 +276,8 @@ object Tests {
|
|||
Output(overall(rs), ms reduce (_ ++ _), Iterable.empty)
|
||||
}
|
||||
}
|
||||
def overall(results: Iterable[TestResult.Value]): TestResult.Value =
|
||||
(TestResult.Passed /: results) { (acc, result) => if (acc.id < result.id) result else acc }
|
||||
def overall(results: Iterable[TestResult]): TestResult =
|
||||
((TestResult.Passed: TestResult) /: results) { (acc, result) => if (severity(acc) < severity(result)) result else acc }
|
||||
def discover(frameworks: Seq[Framework], analysis: CompileAnalysis, log: Logger): (Seq[TestDefinition], Set[String]) =
|
||||
discover(frameworks flatMap TestFramework.getFingerprints, allDefs(analysis), log)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,51 +3,44 @@
|
|||
*/
|
||||
package sbt
|
||||
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
import sbt.internal._
|
||||
import sbt.internal.util.Attributed.data
|
||||
import Scope.{ fillTaskAxis, GlobalScope, ThisScope }
|
||||
import sbt.internal.librarymanagement.mavenint.{ PomExtraDependencyAttributes, SbtPomExtraProperties }
|
||||
import Project.{ inConfig, inScope, inTask, richInitialize, richInitializeTask, richTaskSessionVar }
|
||||
import Def.{ Initialize, ScopedKey, Setting, SettingsDefinition }
|
||||
import sbt.internal.librarymanagement.{ CustomPomParser, DependencyFilter }
|
||||
import sbt.librarymanagement.Artifact.{ DocClassifier, SourceClassifier }
|
||||
import sbt.librarymanagement.{ Configuration, Configurations, ConflictManager, CrossVersion, MavenRepository, Resolver, ScalaArtifacts, UpdateOptions }
|
||||
import sbt.librarymanagement.Configurations.{ Compile, CompilerPlugin, IntegrationTest, names, Provided, Runtime, Test }
|
||||
import sbt.librarymanagement.CrossVersion.{ binarySbtVersion, binaryScalaVersion, partialVersion }
|
||||
import sbt.internal.util.complete._
|
||||
import std.TaskExtra._
|
||||
import testing.{ Framework, Runner, AnnotatedFingerprint, SubclassFingerprint }
|
||||
|
||||
import sjsonnew.{ IsoLList, JsonFormat, LList, LNil }, LList.:*:
|
||||
import sbt.internal.util.CacheImplicits._
|
||||
import sbt.librarymanagement.{ `package` => _, _ }
|
||||
import sbt.internal.librarymanagement._
|
||||
import sbt.internal.librarymanagement.syntax._
|
||||
import sbt.internal.util._
|
||||
import sbt.util.{ Level, Logger, ShowLines }
|
||||
import scala.xml.NodeSeq
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
import org.apache.ivy.core.module.{ descriptor, id }
|
||||
import descriptor.ModuleDescriptor, id.ModuleRevisionId
|
||||
import java.io.{ File, PrintWriter }
|
||||
import java.net.{ URI, URL }
|
||||
import java.util.concurrent.{ TimeUnit, Callable }
|
||||
import sbt.internal.CommandStrings.ExportStream
|
||||
|
||||
import xsbti.{ CrossValue, Maybe }
|
||||
import sbt.util.InterfaceUtil.{ f1, o2m }
|
||||
|
||||
import sbt.internal.util.Types._
|
||||
|
||||
import sbt.internal.io.WatchState
|
||||
import sbt.io.{ AllPassFilter, FileFilter, GlobFilter, HiddenFileFilter, IO, NameFilter, NothingFilter, Path, PathFinder, SimpleFileFilter, DirectoryFilter, Hash }
|
||||
|
||||
import Path._
|
||||
import sbt.io.syntax._
|
||||
import Keys._
|
||||
import org.apache.ivy.core.module.{ descriptor, id }, descriptor.ModuleDescriptor, id.ModuleRevisionId
|
||||
import Project.{ inConfig, inScope, inTask, richInitialize, richInitializeTask, richTaskSessionVar }
|
||||
import sbt.internal._
|
||||
import sbt.internal.CommandStrings.ExportStream
|
||||
import sbt.internal.io.WatchState
|
||||
import sbt.internal.librarymanagement._
|
||||
import sbt.internal.librarymanagement.mavenint.{ PomExtraDependencyAttributes, SbtPomExtraProperties }
|
||||
import sbt.internal.librarymanagement.syntax._
|
||||
import sbt.internal.librarymanagement.{ CustomPomParser, DependencyFilter }
|
||||
import sbt.internal.testing.TestLogger
|
||||
import sbt.internal.util._
|
||||
import sbt.internal.util.Attributed.data
|
||||
import sbt.internal.util.CacheImplicits._
|
||||
import sbt.internal.util.complete._
|
||||
import sbt.internal.util.Types._
|
||||
import sbt.io.syntax._
|
||||
import sbt.io.{ AllPassFilter, FileFilter, GlobFilter, HiddenFileFilter, IO, NameFilter, NothingFilter, Path, PathFinder, SimpleFileFilter, DirectoryFilter, Hash }, Path._
|
||||
import sbt.librarymanagement.Artifact.{ DocClassifier, SourceClassifier }
|
||||
import sbt.librarymanagement.Configurations.{ Compile, CompilerPlugin, IntegrationTest, names, Provided, Runtime, Test }
|
||||
import sbt.librarymanagement.CrossVersion.{ binarySbtVersion, binaryScalaVersion, partialVersion }
|
||||
import sbt.librarymanagement.{ `package` => _, _ }
|
||||
import sbt.librarymanagement.{ Configuration, Configurations, ConflictManager, CrossVersion, MavenRepository, Resolver, ScalaArtifacts, UpdateOptions }
|
||||
import sbt.util.InterfaceUtil.{ f1, o2m }
|
||||
import sbt.util.{ Level, Logger, ShowLines }
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
import scala.util.control.NonFatal
|
||||
import scala.xml.NodeSeq
|
||||
import Scope.{ fillTaskAxis, GlobalScope, ThisScope }
|
||||
import sjsonnew.{ IsoLList, JsonFormat, LList, LNil }, LList.:*:
|
||||
import std.TaskExtra._
|
||||
import testing.{ Framework, Runner, AnnotatedFingerprint, SubclassFingerprint }
|
||||
import xsbti.compile.IncToolOptionsUtil
|
||||
import xsbti.{ CrossValue, Maybe }
|
||||
|
||||
// incremental compiler
|
||||
import xsbt.api.Discovery
|
||||
|
|
|
|||
|
|
@ -10,9 +10,12 @@ import sbt.util.Level
|
|||
import sbt.internal.util._
|
||||
import sbt.protocol.LogEvent
|
||||
import sbt.internal.util.codec._
|
||||
import scala.json.ast.unsafe._
|
||||
|
||||
class RelayAppender(name: String) extends AbstractAppender(name, null, PatternLayout.createDefaultLayout(), true) {
|
||||
import JsonProtocol._
|
||||
lazy val exchange = StandardMain.exchange
|
||||
lazy val jsonFormat = new sjsonnew.BasicJsonProtocol
|
||||
with JValueFormats {}
|
||||
|
||||
def append(event: XLogEvent): Unit =
|
||||
{
|
||||
|
|
@ -26,10 +29,27 @@ class RelayAppender(name: String) extends AbstractAppender(name, null, PatternLa
|
|||
}
|
||||
}
|
||||
def appendLog(level: Level.Value, message: => String): Unit = {
|
||||
StandardMain.exchange.publishEventMessage(LogEvent(level.toString, message))
|
||||
exchange.publishEventMessage(LogEvent(level.toString, message))
|
||||
}
|
||||
def appendEvent(level: Level.Value, event: AnyRef): Unit =
|
||||
event match {
|
||||
case x: StringEvent => StandardMain.exchange.publishEvent(x: AbstractEntry)
|
||||
case x: StringEvent =>
|
||||
{
|
||||
import JsonProtocol._
|
||||
exchange.publishEvent(x: AbstractEntry)
|
||||
}
|
||||
case x: ObjectEvent[_] =>
|
||||
{
|
||||
import jsonFormat._
|
||||
val json = JObject(JField("type", JString(x.contentType)), (
|
||||
Vector(JField("message", x.json),
|
||||
JField("level", JString(x.level.toString))) ++
|
||||
(x.channelName.toVector map { channelName => JField("channelName", JString(channelName)) }) ++
|
||||
(x.execId.toVector map { execId => JField("execId", JString(execId)) })): _*)
|
||||
exchange.publishEvent(json: JValue)
|
||||
}
|
||||
case _ =>
|
||||
println(s"appendEvent: ${event.getClass}")
|
||||
()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ object ContrabandConfig {
|
|||
case "Option" | "Set" | "scala.Vector" => { tpe => getFormats(oneArg(tpe)) }
|
||||
case "Map" | "Tuple2" | "scala.Tuple2" => { tpe => twoArgs(tpe).flatMap(getFormats) }
|
||||
case "Int" | "Long" => { _ => Nil }
|
||||
case "scala.json.ast.unsafe.JValue" => { _ => "sbt.internal.JValueFormat" :: Nil }
|
||||
case "sbt.testing.Status" => { _ => "sbt.internal.testing.StatusFormats" :: Nil }
|
||||
case "scala.json.ast.unsafe.JValue" => { _ => "sbt.internal.util.codec.JValueFormats" :: Nil }
|
||||
}
|
||||
|
||||
/** Returns the list of formats required to encode the given `TpeRef`. */
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ object Dependencies {
|
|||
|
||||
// sbt modules
|
||||
private val ioVersion = "1.0.0-M9"
|
||||
private val utilVersion = "1.0.0-M20"
|
||||
private val utilVersion = "1.0.0-M21"
|
||||
private val lmVersion = "1.0.0-X7"
|
||||
private val zincVersion = "1.0.0-X11"
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait EventMessageFormats { self: sjsonnew.BasicJsonProtocol with sbt.protocol.codec.ChannelAcceptedEventFormats with sbt.protocol.codec.LogEventFormats with sbt.protocol.codec.ExecStatusEventFormats with sbt.internal.JValueFormat with sbt.protocol.codec.SettingQuerySuccessFormats with sbt.protocol.codec.SettingQueryFailureFormats =>
|
||||
trait EventMessageFormats { self: sjsonnew.BasicJsonProtocol with sbt.protocol.codec.ChannelAcceptedEventFormats with sbt.protocol.codec.LogEventFormats with sbt.protocol.codec.ExecStatusEventFormats with sbt.internal.util.codec.JValueFormats with sbt.protocol.codec.SettingQuerySuccessFormats with sbt.protocol.codec.SettingQueryFailureFormats =>
|
||||
implicit lazy val EventMessageFormat: JsonFormat[sbt.protocol.EventMessage] = flatUnionFormat5[sbt.protocol.EventMessage, sbt.protocol.ChannelAcceptedEvent, sbt.protocol.LogEvent, sbt.protocol.ExecStatusEvent, sbt.protocol.SettingQuerySuccess, sbt.protocol.SettingQueryFailure]("type")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
|||
with sbt.protocol.codec.ChannelAcceptedEventFormats
|
||||
with sbt.protocol.codec.LogEventFormats
|
||||
with sbt.protocol.codec.ExecStatusEventFormats
|
||||
with sbt.internal.JValueFormat
|
||||
with sbt.internal.util.codec.JValueFormats
|
||||
with sbt.protocol.codec.SettingQuerySuccessFormats
|
||||
with sbt.protocol.codec.SettingQueryFailureFormats
|
||||
with sbt.protocol.codec.EventMessageFormats
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait SettingQueryResponseFormats { self: sbt.internal.JValueFormat with sjsonnew.BasicJsonProtocol with sbt.protocol.codec.SettingQuerySuccessFormats with sbt.protocol.codec.SettingQueryFailureFormats =>
|
||||
trait SettingQueryResponseFormats { self: sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol with sbt.protocol.codec.SettingQuerySuccessFormats with sbt.protocol.codec.SettingQueryFailureFormats =>
|
||||
implicit lazy val SettingQueryResponseFormat: JsonFormat[sbt.protocol.SettingQueryResponse] = flatUnionFormat2[sbt.protocol.SettingQueryResponse, sbt.protocol.SettingQuerySuccess, sbt.protocol.SettingQueryFailure]("type")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait SettingQuerySuccessFormats { self: sbt.internal.JValueFormat with sjsonnew.BasicJsonProtocol =>
|
||||
trait SettingQuerySuccessFormats { self: sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val SettingQuerySuccessFormat: JsonFormat[sbt.protocol.SettingQuerySuccess] = new JsonFormat[sbt.protocol.SettingQuerySuccess] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.SettingQuerySuccess = {
|
||||
jsOpt match {
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Lightbend Inc. <http://www.lightbend.com>
|
||||
*/
|
||||
package sbt
|
||||
package internal
|
||||
|
||||
import sjsonnew.{ JsonWriter => JW, JsonReader => JR, JsonFormat => JF, _ }
|
||||
import scala.json.ast.unsafe._
|
||||
|
||||
trait JValueFormat { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit val JNullJF: JF[JNull.type] = new JF[JNull.type] {
|
||||
def write[J](x: JNull.type, b: Builder[J]) = b.writeNull()
|
||||
def read[J](j: Option[J], u: Unbuilder[J]) = JNull
|
||||
}
|
||||
|
||||
implicit val JBooleanJF: JF[JBoolean] = project(_.get, JBoolean(_))
|
||||
implicit val JStringJF: JF[JString] = project(_.value, JString(_))
|
||||
implicit val JNumberJF: JF[JNumber] = project(x => BigDecimal(x.value), (x: BigDecimal) => JNumber(x.toString))
|
||||
implicit val JArrayJF: JF[JArray] = project[JArray, Array[JValue]](_.value, JArray(_))
|
||||
|
||||
implicit lazy val JObjectJW: JW[JObject] = new JW[JObject] {
|
||||
def write[J](x: JObject, b: Builder[J]) = {
|
||||
b.beginObject()
|
||||
x.value foreach (jsonField => JValueJW.addField(jsonField.field, jsonField.value, b))
|
||||
b.endObject()
|
||||
}
|
||||
}
|
||||
|
||||
implicit lazy val JValueJW: JW[JValue] = new JW[JValue] {
|
||||
def write[J](x: JValue, b: Builder[J]) = x match {
|
||||
case x: JNull.type => JNullJF.write(x, b)
|
||||
case x: JBoolean => JBooleanJF.write(x, b)
|
||||
case x: JString => JStringJF.write(x, b)
|
||||
case x: JNumber => JNumberJF.write(x, b)
|
||||
case x: JArray => JArrayJF.write(x, b)
|
||||
case x: JObject => JObjectJW.write(x, b)
|
||||
}
|
||||
}
|
||||
|
||||
implicit lazy val JValueJR: JR[JValue] = new JR[JValue] {
|
||||
def read[J](j: Option[J], u: Unbuilder[J]) = ??? // Is this even possible? with no Manifest[J]?
|
||||
}
|
||||
|
||||
implicit lazy val JValueJF: JF[JValue] = jsonFormat[JValue](JValueJR, JValueJW)
|
||||
}
|
||||
|
|
@ -8,6 +8,10 @@ trait Import {
|
|||
type URI = java.net.URI
|
||||
type URL = java.net.URL
|
||||
|
||||
// sbt.testing
|
||||
type TestResult = sbt.protocol.testing.TestResult
|
||||
val TestResult = sbt.protocol.testing.TestResult
|
||||
|
||||
// sbt.io
|
||||
val AllPassFilter = sbt.io.AllPassFilter
|
||||
val DirectoryFilter = sbt.io.DirectoryFilter
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ lazy val root = (project in file(".")).
|
|||
}
|
||||
def startGroup(name: String): Unit = ()
|
||||
def endGroup(name: String, t: Throwable): Unit = ()
|
||||
def endGroup(name: String, result: TestResult.Value): Unit = ()
|
||||
def endGroup(name: String, result: TestResult): Unit = ()
|
||||
},
|
||||
check := {
|
||||
val exists = marker.exists
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Called if test completed with an error. */
|
||||
final class EndTestGroupErrorEvent private (
|
||||
val name: String,
|
||||
val error: String) extends sbt.protocol.testing.TestMessage() with Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: EndTestGroupErrorEvent => (this.name == x.name) && (this.error == x.error)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (17 + name.##) + error.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"EndTestGroupErrorEvent(" + name + ", " + error + ")"
|
||||
}
|
||||
protected[this] def copy(name: String = name, error: String = error): EndTestGroupErrorEvent = {
|
||||
new EndTestGroupErrorEvent(name, error)
|
||||
}
|
||||
def withName(name: String): EndTestGroupErrorEvent = {
|
||||
copy(name = name)
|
||||
}
|
||||
def withError(error: String): EndTestGroupErrorEvent = {
|
||||
copy(error = error)
|
||||
}
|
||||
}
|
||||
object EndTestGroupErrorEvent {
|
||||
|
||||
def apply(name: String, error: String): EndTestGroupErrorEvent = new EndTestGroupErrorEvent(name, error)
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Called if test completed. */
|
||||
final class EndTestGroupEvent private (
|
||||
val name: String,
|
||||
val result: sbt.protocol.testing.TestResult) extends sbt.protocol.testing.TestMessage() with Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: EndTestGroupEvent => (this.name == x.name) && (this.result == x.result)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (17 + name.##) + result.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"EndTestGroupEvent(" + name + ", " + result + ")"
|
||||
}
|
||||
protected[this] def copy(name: String = name, result: sbt.protocol.testing.TestResult = result): EndTestGroupEvent = {
|
||||
new EndTestGroupEvent(name, result)
|
||||
}
|
||||
def withName(name: String): EndTestGroupEvent = {
|
||||
copy(name = name)
|
||||
}
|
||||
def withResult(result: sbt.protocol.testing.TestResult): EndTestGroupEvent = {
|
||||
copy(result = result)
|
||||
}
|
||||
}
|
||||
object EndTestGroupEvent {
|
||||
|
||||
def apply(name: String, result: sbt.protocol.testing.TestResult): EndTestGroupEvent = new EndTestGroupEvent(name, result)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Called for each class or equivalent grouping. */
|
||||
final class StartTestGroupEvent private (
|
||||
val name: String) extends sbt.protocol.testing.TestMessage() with Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: StartTestGroupEvent => (this.name == x.name)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (17 + name.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"StartTestGroupEvent(" + name + ")"
|
||||
}
|
||||
protected[this] def copy(name: String = name): StartTestGroupEvent = {
|
||||
new StartTestGroupEvent(name)
|
||||
}
|
||||
def withName(name: String): StartTestGroupEvent = {
|
||||
copy(name = name)
|
||||
}
|
||||
}
|
||||
object StartTestGroupEvent {
|
||||
|
||||
def apply(name: String): StartTestGroupEvent = new StartTestGroupEvent(name)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Called once, at end of the testing. */
|
||||
final class TestCompleteEvent private (
|
||||
val result: sbt.protocol.testing.TestResult) extends sbt.protocol.testing.TestMessage() with Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: TestCompleteEvent => (this.result == x.result)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (17 + result.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"TestCompleteEvent(" + result + ")"
|
||||
}
|
||||
protected[this] def copy(result: sbt.protocol.testing.TestResult = result): TestCompleteEvent = {
|
||||
new TestCompleteEvent(result)
|
||||
}
|
||||
def withResult(result: sbt.protocol.testing.TestResult): TestCompleteEvent = {
|
||||
copy(result = result)
|
||||
}
|
||||
}
|
||||
object TestCompleteEvent {
|
||||
|
||||
def apply(result: sbt.protocol.testing.TestResult): TestCompleteEvent = new TestCompleteEvent(result)
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Called once, at beginning of the testing. */
|
||||
final class TestInitEvent private () extends sbt.protocol.testing.TestMessage() with Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: TestInitEvent => true
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
17
|
||||
}
|
||||
override def toString: String = {
|
||||
"TestInitEvent()"
|
||||
}
|
||||
protected[this] def copy(): TestInitEvent = {
|
||||
new TestInitEvent()
|
||||
}
|
||||
|
||||
}
|
||||
object TestInitEvent {
|
||||
|
||||
def apply(): TestInitEvent = new TestInitEvent()
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Mini version of sbt.testing.Event */
|
||||
final class TestItemDetail private (
|
||||
/**
|
||||
* The fully qualified name of a class that can rerun the suite or test
|
||||
* about which an event was fired.
|
||||
*/
|
||||
val fullyQualifiedName: String,
|
||||
/** Indicates whether the event represents a test success, failure, error, skipped, ignored, canceled, pending. */
|
||||
val status: sbt.testing.Status,
|
||||
/**
|
||||
* An amount of time, in milliseconds, that was required to complete the action reported by this event.
|
||||
* None, if no duration was available.
|
||||
*/
|
||||
val duration: Option[Long]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: TestItemDetail => (this.fullyQualifiedName == x.fullyQualifiedName) && (this.status == x.status) && (this.duration == x.duration)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + fullyQualifiedName.##) + status.##) + duration.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"TestItemDetail(" + fullyQualifiedName + ", " + status + ", " + duration + ")"
|
||||
}
|
||||
protected[this] def copy(fullyQualifiedName: String = fullyQualifiedName, status: sbt.testing.Status = status, duration: Option[Long] = duration): TestItemDetail = {
|
||||
new TestItemDetail(fullyQualifiedName, status, duration)
|
||||
}
|
||||
def withFullyQualifiedName(fullyQualifiedName: String): TestItemDetail = {
|
||||
copy(fullyQualifiedName = fullyQualifiedName)
|
||||
}
|
||||
def withStatus(status: sbt.testing.Status): TestItemDetail = {
|
||||
copy(status = status)
|
||||
}
|
||||
def withDuration(duration: Option[Long]): TestItemDetail = {
|
||||
copy(duration = duration)
|
||||
}
|
||||
def withDuration(duration: Long): TestItemDetail = {
|
||||
copy(duration = Option(duration))
|
||||
}
|
||||
}
|
||||
object TestItemDetail {
|
||||
|
||||
def apply(fullyQualifiedName: String, status: sbt.testing.Status, duration: Option[Long]): TestItemDetail = new TestItemDetail(fullyQualifiedName, status, duration)
|
||||
def apply(fullyQualifiedName: String, status: sbt.testing.Status, duration: Long): TestItemDetail = new TestItemDetail(fullyQualifiedName, status, Option(duration))
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Called for each test method or equivalent. */
|
||||
final class TestItemEvent private (
|
||||
val result: Option[sbt.protocol.testing.TestResult],
|
||||
val detail: Vector[sbt.protocol.testing.TestItemDetail]) extends sbt.protocol.testing.TestMessage() with Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: TestItemEvent => (this.result == x.result) && (this.detail == x.detail)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (17 + result.##) + detail.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"TestItemEvent(" + result + ", " + detail + ")"
|
||||
}
|
||||
protected[this] def copy(result: Option[sbt.protocol.testing.TestResult] = result, detail: Vector[sbt.protocol.testing.TestItemDetail] = detail): TestItemEvent = {
|
||||
new TestItemEvent(result, detail)
|
||||
}
|
||||
def withResult(result: Option[sbt.protocol.testing.TestResult]): TestItemEvent = {
|
||||
copy(result = result)
|
||||
}
|
||||
def withResult(result: sbt.protocol.testing.TestResult): TestItemEvent = {
|
||||
copy(result = Option(result))
|
||||
}
|
||||
def withDetail(detail: Vector[sbt.protocol.testing.TestItemDetail]): TestItemEvent = {
|
||||
copy(detail = detail)
|
||||
}
|
||||
}
|
||||
object TestItemEvent {
|
||||
|
||||
def apply(result: Option[sbt.protocol.testing.TestResult], detail: Vector[sbt.protocol.testing.TestItemDetail]): TestItemEvent = new TestItemEvent(result, detail)
|
||||
def apply(result: sbt.protocol.testing.TestResult, detail: Vector[sbt.protocol.testing.TestItemDetail]): TestItemEvent = new TestItemEvent(Option(result), detail)
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Events for testing */
|
||||
abstract class TestMessage() extends Serializable {
|
||||
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: TestMessage => true
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
17
|
||||
}
|
||||
override def toString: String = {
|
||||
"TestMessage()"
|
||||
}
|
||||
}
|
||||
object TestMessage {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
/** Testing result */
|
||||
sealed abstract class TestResult extends Serializable
|
||||
object TestResult {
|
||||
|
||||
|
||||
case object Passed extends TestResult
|
||||
case object Failed extends TestResult
|
||||
case object Error extends TestResult
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing
|
||||
final class TestStringEvent private (
|
||||
val value: String) extends sbt.protocol.testing.TestMessage() with Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case x: TestStringEvent => (this.value == x.value)
|
||||
case _ => false
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (17 + value.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
value
|
||||
}
|
||||
protected[this] def copy(value: String = value): TestStringEvent = {
|
||||
new TestStringEvent(value)
|
||||
}
|
||||
def withValue(value: String): TestStringEvent = {
|
||||
copy(value = value)
|
||||
}
|
||||
}
|
||||
object TestStringEvent {
|
||||
|
||||
def apply(value: String): TestStringEvent = new TestStringEvent(value)
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait EndTestGroupErrorEventFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val EndTestGroupErrorEventFormat: JsonFormat[sbt.protocol.testing.EndTestGroupErrorEvent] = new JsonFormat[sbt.protocol.testing.EndTestGroupErrorEvent] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.EndTestGroupErrorEvent = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
val name = unbuilder.readField[String]("name")
|
||||
val error = unbuilder.readField[String]("error")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.EndTestGroupErrorEvent(name, error)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.EndTestGroupErrorEvent, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("name", obj.name)
|
||||
builder.addField("error", obj.error)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait EndTestGroupEventFormats { self: sbt.protocol.testing.codec.TestResultFormats with sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val EndTestGroupEventFormat: JsonFormat[sbt.protocol.testing.EndTestGroupEvent] = new JsonFormat[sbt.protocol.testing.EndTestGroupEvent] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.EndTestGroupEvent = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
val name = unbuilder.readField[String]("name")
|
||||
val result = unbuilder.readField[sbt.protocol.testing.TestResult]("result")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.EndTestGroupEvent(name, result)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.EndTestGroupEvent, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("name", obj.name)
|
||||
builder.addField("result", obj.result)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
||||
with sbt.protocol.testing.codec.TestStringEventFormats
|
||||
with sbt.protocol.testing.codec.TestInitEventFormats
|
||||
with sbt.protocol.testing.codec.TestResultFormats
|
||||
with sbt.protocol.testing.codec.TestCompleteEventFormats
|
||||
with sbt.protocol.testing.codec.StartTestGroupEventFormats
|
||||
with sbt.protocol.testing.codec.EndTestGroupEventFormats
|
||||
with sbt.protocol.testing.codec.EndTestGroupErrorEventFormats
|
||||
with sbt.internal.testing.StatusFormats
|
||||
with sbt.protocol.testing.codec.TestItemDetailFormats
|
||||
with sbt.protocol.testing.codec.TestItemEventFormats
|
||||
with sbt.protocol.testing.codec.TestMessageFormats
|
||||
object JsonProtocol extends JsonProtocol
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait StartTestGroupEventFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val StartTestGroupEventFormat: JsonFormat[sbt.protocol.testing.StartTestGroupEvent] = new JsonFormat[sbt.protocol.testing.StartTestGroupEvent] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.StartTestGroupEvent = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
val name = unbuilder.readField[String]("name")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.StartTestGroupEvent(name)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.StartTestGroupEvent, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("name", obj.name)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait TestCompleteEventFormats { self: sbt.protocol.testing.codec.TestResultFormats with sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val TestCompleteEventFormat: JsonFormat[sbt.protocol.testing.TestCompleteEvent] = new JsonFormat[sbt.protocol.testing.TestCompleteEvent] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.TestCompleteEvent = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
val result = unbuilder.readField[sbt.protocol.testing.TestResult]("result")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.TestCompleteEvent(result)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.TestCompleteEvent, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("result", obj.result)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait TestInitEventFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val TestInitEventFormat: JsonFormat[sbt.protocol.testing.TestInitEvent] = new JsonFormat[sbt.protocol.testing.TestInitEvent] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.TestInitEvent = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.TestInitEvent()
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.TestInitEvent, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait TestItemDetailFormats { self: sbt.internal.testing.StatusFormats with sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val TestItemDetailFormat: JsonFormat[sbt.protocol.testing.TestItemDetail] = new JsonFormat[sbt.protocol.testing.TestItemDetail] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.TestItemDetail = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
val fullyQualifiedName = unbuilder.readField[String]("fullyQualifiedName")
|
||||
val status = unbuilder.readField[sbt.testing.Status]("status")
|
||||
val duration = unbuilder.readField[Option[Long]]("duration")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.TestItemDetail(fullyQualifiedName, status, duration)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.TestItemDetail, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("fullyQualifiedName", obj.fullyQualifiedName)
|
||||
builder.addField("status", obj.status)
|
||||
builder.addField("duration", obj.duration)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait TestItemEventFormats { self: sbt.protocol.testing.codec.TestResultFormats with sbt.protocol.testing.codec.TestItemDetailFormats with sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val TestItemEventFormat: JsonFormat[sbt.protocol.testing.TestItemEvent] = new JsonFormat[sbt.protocol.testing.TestItemEvent] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.TestItemEvent = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
val result = unbuilder.readField[Option[sbt.protocol.testing.TestResult]]("result")
|
||||
val detail = unbuilder.readField[Vector[sbt.protocol.testing.TestItemDetail]]("detail")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.TestItemEvent(result, detail)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.TestItemEvent, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("result", obj.result)
|
||||
builder.addField("detail", obj.detail)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait TestMessageFormats { self: sjsonnew.BasicJsonProtocol with sbt.protocol.testing.codec.TestStringEventFormats with sbt.protocol.testing.codec.TestInitEventFormats with sbt.protocol.testing.codec.TestResultFormats with sbt.protocol.testing.codec.TestCompleteEventFormats with sbt.protocol.testing.codec.StartTestGroupEventFormats with sbt.protocol.testing.codec.EndTestGroupEventFormats with sbt.protocol.testing.codec.EndTestGroupErrorEventFormats with sbt.protocol.testing.codec.TestItemDetailFormats with sbt.protocol.testing.codec.TestItemEventFormats =>
|
||||
implicit lazy val TestMessageFormat: JsonFormat[sbt.protocol.testing.TestMessage] = flatUnionFormat7[sbt.protocol.testing.TestMessage, sbt.protocol.testing.TestStringEvent, sbt.protocol.testing.TestInitEvent, sbt.protocol.testing.TestCompleteEvent, sbt.protocol.testing.StartTestGroupEvent, sbt.protocol.testing.EndTestGroupEvent, sbt.protocol.testing.EndTestGroupErrorEvent, sbt.protocol.testing.TestItemEvent]("type")
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait TestResultFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val TestResultFormat: JsonFormat[sbt.protocol.testing.TestResult] = new JsonFormat[sbt.protocol.testing.TestResult] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.TestResult = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.readString(js) match {
|
||||
case "Passed" => sbt.protocol.testing.TestResult.Passed
|
||||
case "Failed" => sbt.protocol.testing.TestResult.Failed
|
||||
case "Error" => sbt.protocol.testing.TestResult.Error
|
||||
}
|
||||
case None =>
|
||||
deserializationError("Expected JsString but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.TestResult, builder: Builder[J]): Unit = {
|
||||
val str = obj match {
|
||||
case sbt.protocol.testing.TestResult.Passed => "Passed"
|
||||
case sbt.protocol.testing.TestResult.Failed => "Failed"
|
||||
case sbt.protocol.testing.TestResult.Error => "Error"
|
||||
}
|
||||
builder.writeString(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.testing.codec
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
trait TestStringEventFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val TestStringEventFormat: JsonFormat[sbt.protocol.testing.TestStringEvent] = new JsonFormat[sbt.protocol.testing.TestStringEvent] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.testing.TestStringEvent = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.beginObject(js)
|
||||
val value = unbuilder.readField[String]("value")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.testing.TestStringEvent(value)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.protocol.testing.TestStringEvent, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("value", obj.value)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package sbt.protocol.testing
|
||||
@target(Scala)
|
||||
@codecPackage("sbt.protocol.testing.codec")
|
||||
@fullCodec("JsonProtocol")
|
||||
|
||||
## Events for testing
|
||||
interface TestMessage {
|
||||
}
|
||||
|
||||
type TestStringEvent implements TestMessage {
|
||||
value: String!
|
||||
#xtostring value
|
||||
}
|
||||
|
||||
## Called once, at beginning of the testing.
|
||||
type TestInitEvent implements TestMessage {}
|
||||
|
||||
## Called once, at end of the testing.
|
||||
type TestCompleteEvent implements TestMessage {
|
||||
result: sbt.protocol.testing.TestResult!
|
||||
}
|
||||
|
||||
## Called for each class or equivalent grouping.
|
||||
type StartTestGroupEvent implements TestMessage {
|
||||
name: String!
|
||||
}
|
||||
|
||||
## Called if test completed.
|
||||
type EndTestGroupEvent implements TestMessage {
|
||||
name: String!
|
||||
result: sbt.protocol.testing.TestResult!
|
||||
}
|
||||
|
||||
## Called if test completed with an error.
|
||||
type EndTestGroupErrorEvent implements TestMessage {
|
||||
name: String!
|
||||
error: String!
|
||||
}
|
||||
|
||||
## Called for each test method or equivalent.
|
||||
type TestItemEvent implements TestMessage {
|
||||
result: sbt.protocol.testing.TestResult
|
||||
detail: [sbt.protocol.testing.TestItemDetail]
|
||||
}
|
||||
|
||||
## Mini version of sbt.testing.Event
|
||||
type TestItemDetail {
|
||||
## The fully qualified name of a class that can rerun the suite or test
|
||||
## about which an event was fired.
|
||||
fullyQualifiedName: String!
|
||||
|
||||
## Indicates whether the event represents a test success, failure, error, skipped, ignored, canceled, pending.
|
||||
status: sbt.testing.Status!
|
||||
|
||||
## An amount of time, in milliseconds, that was required to complete the action reported by this event.
|
||||
## None, if no duration was available.
|
||||
duration: Long
|
||||
}
|
||||
|
||||
## Testing result
|
||||
enum TestResult {
|
||||
Passed
|
||||
Failed
|
||||
Error
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import scala.collection.mutable.ListBuffer
|
|||
import scala.util.DynamicVariable
|
||||
import scala.xml.{ Elem, Node => XNode, XML }
|
||||
import testing.{ Event => TEvent, Status => TStatus, OptionalThrowable, TestSelector }
|
||||
import sbt.protocol.testing.TestResult
|
||||
|
||||
/**
|
||||
* A tests listener that outputs the results it receives in junit xml
|
||||
|
|
@ -161,7 +162,7 @@ class JUnitXmlTestsListener(val outputDir: String) extends TestsListener {
|
|||
* Ends the current suite, wraps up the result and writes it to an XML file
|
||||
* in the output folder that is named after the suite.
|
||||
*/
|
||||
override def endGroup(name: String, result: TestResult.Value) = {
|
||||
override def endGroup(name: String, result: TestResult) = {
|
||||
writeSuite()
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +178,7 @@ class JUnitXmlTestsListener(val outputDir: String) extends TestsListener {
|
|||
}
|
||||
|
||||
/**Does nothing, as we write each file after a suite is done.*/
|
||||
override def doComplete(finalResult: TestResult.Value): Unit = {}
|
||||
override def doComplete(finalResult: TestResult): Unit = {}
|
||||
|
||||
/**Returns None*/
|
||||
override def contentLogger(test: TestDefinition): Option[ContentLogger] = None
|
||||
|
|
|
|||
|
|
@ -10,12 +10,9 @@ import org.scalatools.testing.{ Framework => OldFramework }
|
|||
import sbt.internal.inc.classpath.{ ClasspathUtilities, DualLoader }
|
||||
import sbt.internal.inc.ScalaInstance
|
||||
import scala.annotation.tailrec
|
||||
import sbt.util.Logger
|
||||
import sbt.internal.util.ManagedLogger
|
||||
import sbt.io.IO
|
||||
|
||||
object TestResult extends Enumeration {
|
||||
val Passed, Failed, Error = Value
|
||||
}
|
||||
import sbt.protocol.testing.TestResult
|
||||
|
||||
object TestFrameworks {
|
||||
val ScalaCheck = new TestFramework("org.scalacheck.ScalaCheckFramework")
|
||||
|
|
@ -27,7 +24,7 @@ object TestFrameworks {
|
|||
|
||||
case class TestFramework(implClassNames: String*) {
|
||||
@tailrec
|
||||
private def createFramework(loader: ClassLoader, log: Logger, frameworkClassNames: List[String]): Option[Framework] = {
|
||||
private def createFramework(loader: ClassLoader, log: ManagedLogger, frameworkClassNames: List[String]): Option[Framework] = {
|
||||
frameworkClassNames match {
|
||||
case head :: tail =>
|
||||
try {
|
||||
|
|
@ -45,7 +42,7 @@ case class TestFramework(implClassNames: String*) {
|
|||
}
|
||||
}
|
||||
|
||||
def create(loader: ClassLoader, log: Logger): Option[Framework] =
|
||||
def create(loader: ClassLoader, log: ManagedLogger): Option[Framework] =
|
||||
createFramework(loader, log, implClassNames.toList)
|
||||
}
|
||||
final class TestDefinition(val name: String, val fingerprint: Fingerprint, val explicitlySpecified: Boolean, val selectors: Array[Selector]) {
|
||||
|
|
@ -58,7 +55,7 @@ final class TestDefinition(val name: String, val fingerprint: Fingerprint, val e
|
|||
override def hashCode: Int = (name.hashCode, TestFramework.hashCode(fingerprint)).hashCode
|
||||
}
|
||||
|
||||
final class TestRunner(delegate: Runner, listeners: Seq[TestReportListener], log: Logger) {
|
||||
final class TestRunner(delegate: Runner, listeners: Seq[TestReportListener], log: ManagedLogger) {
|
||||
|
||||
final def tasks(testDefs: Set[TestDefinition]): Array[TestTask] =
|
||||
delegate.tasks(testDefs.map(df => new TaskDef(df.name, df.fingerprint, df.explicitlySpecified, df.selectors)).toArray)
|
||||
|
|
@ -106,7 +103,7 @@ object TestFramework {
|
|||
case _ => sys.error("Could not call 'fingerprints' on framework " + framework)
|
||||
}
|
||||
|
||||
private[sbt] def safeForeach[T](it: Iterable[T], log: Logger)(f: T => Unit): Unit =
|
||||
private[sbt] def safeForeach[T](it: Iterable[T], log: ManagedLogger)(f: T => Unit): Unit =
|
||||
it.foreach(i => try f(i) catch { case NonFatal(e) => log.trace(e); log.error(e.toString) })
|
||||
|
||||
private[sbt] def hashCode(f: Fingerprint): Int = f match {
|
||||
|
|
@ -132,9 +129,9 @@ object TestFramework {
|
|||
runners: Map[TestFramework, Runner],
|
||||
testLoader: ClassLoader,
|
||||
tests: Seq[TestDefinition],
|
||||
log: Logger,
|
||||
log: ManagedLogger,
|
||||
listeners: Seq[TestReportListener]
|
||||
): (() => Unit, Seq[(String, TestFunction)], TestResult.Value => () => Unit) =
|
||||
): (() => Unit, Seq[(String, TestFunction)], TestResult => () => Unit) =
|
||||
{
|
||||
val mappedTests = testMap(frameworks.values.toSeq, tests)
|
||||
if (mappedTests.isEmpty)
|
||||
|
|
@ -160,7 +157,7 @@ object TestFramework {
|
|||
map.toMap.mapValues(_.toSet)
|
||||
}
|
||||
|
||||
private def createTestTasks(loader: ClassLoader, runners: Map[Framework, TestRunner], tests: Map[Framework, Set[TestDefinition]], ordered: Seq[TestDefinition], log: Logger, listeners: Seq[TestReportListener]) =
|
||||
private def createTestTasks(loader: ClassLoader, runners: Map[Framework, TestRunner], tests: Map[Framework, Set[TestDefinition]], ordered: Seq[TestDefinition], log: ManagedLogger, listeners: Seq[TestReportListener]) =
|
||||
{
|
||||
val testsListeners = listeners collect { case tl: TestsListener => tl }
|
||||
|
||||
|
|
@ -178,7 +175,7 @@ object TestFramework {
|
|||
}
|
||||
}
|
||||
|
||||
val endTask = (result: TestResult.Value) => foreachListenerSafe(_.doComplete(result))
|
||||
val endTask = (result: TestResult) => foreachListenerSafe(_.doComplete(result))
|
||||
(startTask, order(testTasks, ordered), endTask)
|
||||
}
|
||||
private[this] def withContextLoader[T](loader: ClassLoader)(eval: => T): T =
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
package sbt
|
||||
|
||||
import testing.{ Logger => TLogger, Event => TEvent, Status => TStatus }
|
||||
import sbt.internal.util.{ BufferedLogger, FullLogger }
|
||||
import sbt.util.Level
|
||||
import sbt.protocol.testing._
|
||||
|
||||
trait TestReportListener {
|
||||
/** called for each class or equivalent grouping */
|
||||
|
|
@ -19,23 +18,25 @@ trait TestReportListener {
|
|||
def endGroup(name: String, t: Throwable): Unit
|
||||
|
||||
/** called if test completed */
|
||||
def endGroup(name: String, result: TestResult.Value): Unit
|
||||
def endGroup(name: String, result: TestResult): Unit
|
||||
|
||||
/** Used by the test framework for logging test results*/
|
||||
def contentLogger(test: TestDefinition): Option[ContentLogger] = None
|
||||
}
|
||||
|
||||
final class ContentLogger(val log: TLogger, val flush: () => Unit)
|
||||
|
||||
trait TestsListener extends TestReportListener {
|
||||
/** called once, at beginning. */
|
||||
def doInit(): Unit
|
||||
|
||||
/** called once, at end. */
|
||||
def doComplete(finalResult: TestResult.Value): Unit
|
||||
def doComplete(finalResult: TestResult): Unit
|
||||
}
|
||||
|
||||
/** Provides the overall `result` of a group of tests (a suite) and test counts for each result type. */
|
||||
final class SuiteResult(
|
||||
val result: TestResult.Value,
|
||||
val result: TestResult,
|
||||
val passedCount: Int, val failureCount: Int, val errorCount: Int,
|
||||
val skippedCount: Int, val ignoredCount: Int, val canceledCount: Int, val pendingCount: Int
|
||||
) {
|
||||
|
|
@ -65,7 +66,7 @@ object SuiteResult {
|
|||
}
|
||||
|
||||
abstract class TestEvent {
|
||||
def result: Option[TestResult.Value]
|
||||
def result: Option[TestResult]
|
||||
def detail: Seq[TEvent] = Nil
|
||||
}
|
||||
object TestEvent {
|
||||
|
|
@ -75,8 +76,8 @@ object TestEvent {
|
|||
override val detail = events
|
||||
}
|
||||
|
||||
private[sbt] def overallResult(events: Seq[TEvent]): TestResult.Value =
|
||||
(TestResult.Passed /: events) { (sum, event) =>
|
||||
private[sbt] def overallResult(events: Seq[TEvent]): TestResult =
|
||||
((TestResult.Passed: TestResult) /: events) { (sum, event) =>
|
||||
(sum, event.status) match {
|
||||
case (TestResult.Error, _) => TestResult.Error
|
||||
case (_, TStatus.Error) => TestResult.Error
|
||||
|
|
@ -86,60 +87,3 @@ object TestEvent {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TestLogger {
|
||||
@deprecated("Doesn't provide for underlying resources to be released.", "0.13.1")
|
||||
def apply(logger: sbt.util.Logger, logTest: TestDefinition => sbt.util.Logger, buffered: Boolean): TestLogger =
|
||||
new TestLogger(new TestLogging(wrap(logger), tdef => contentLogger(logTest(tdef), buffered)))
|
||||
|
||||
@deprecated("Doesn't provide for underlying resources to be released.", "0.13.1")
|
||||
def contentLogger(log: sbt.util.Logger, buffered: Boolean): ContentLogger =
|
||||
{
|
||||
val blog = new BufferedLogger(FullLogger(log))
|
||||
if (buffered) blog.record()
|
||||
new ContentLogger(wrap(blog), () => blog.stopQuietly())
|
||||
}
|
||||
|
||||
final class PerTest private[sbt] (val log: sbt.util.Logger, val flush: () => Unit, val buffered: Boolean)
|
||||
|
||||
def make(global: sbt.util.Logger, perTest: TestDefinition => PerTest): TestLogger =
|
||||
{
|
||||
def makePerTest(tdef: TestDefinition): ContentLogger =
|
||||
{
|
||||
val per = perTest(tdef)
|
||||
val blog = new BufferedLogger(FullLogger(per.log))
|
||||
if (per.buffered) blog.record()
|
||||
new ContentLogger(wrap(blog), () => { blog.stopQuietly(); per.flush() })
|
||||
}
|
||||
val config = new TestLogging(wrap(global), makePerTest)
|
||||
new TestLogger(config)
|
||||
}
|
||||
|
||||
def wrap(logger: sbt.util.Logger): TLogger =
|
||||
new TLogger {
|
||||
def error(s: String) = log(Level.Error, s)
|
||||
def warn(s: String) = log(Level.Warn, s)
|
||||
def info(s: String) = log(Level.Info, s)
|
||||
def debug(s: String) = log(Level.Debug, s)
|
||||
def trace(t: Throwable) = logger.trace(t)
|
||||
private def log(level: Level.Value, s: String) = logger.log(level, s)
|
||||
def ansiCodesSupported() = logger.ansiCodesSupported
|
||||
}
|
||||
}
|
||||
final class TestLogging(val global: TLogger, val logTest: TestDefinition => ContentLogger)
|
||||
final class ContentLogger(val log: TLogger, val flush: () => Unit)
|
||||
class TestLogger(val logging: TestLogging) extends TestsListener {
|
||||
import logging.{ global => log, logTest }
|
||||
|
||||
def startGroup(name: String): Unit = ()
|
||||
def testEvent(event: TestEvent): Unit = ()
|
||||
def endGroup(name: String, t: Throwable): Unit = {
|
||||
log.trace(t)
|
||||
log.error("Could not run test " + name + ": " + t.toString)
|
||||
}
|
||||
def endGroup(name: String, result: TestResult.Value): Unit = ()
|
||||
def doInit: Unit = ()
|
||||
/** called once, at end of test group. */
|
||||
def doComplete(finalResult: TestResult.Value): Unit = ()
|
||||
override def contentLogger(test: TestDefinition): Option[ContentLogger] = Some(logTest(test))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import java.io.File
|
|||
import sbt.io.IO
|
||||
|
||||
import scala.collection.mutable.Map
|
||||
import sbt.protocol.testing.TestResult
|
||||
|
||||
// Assumes exclusive ownership of the file.
|
||||
private[sbt] class TestStatusReporter(f: File) extends TestsListener {
|
||||
|
|
@ -16,11 +17,11 @@ private[sbt] class TestStatusReporter(f: File) extends TestsListener {
|
|||
def startGroup(name: String): Unit = { succeeded remove name }
|
||||
def testEvent(event: TestEvent): Unit = ()
|
||||
def endGroup(name: String, t: Throwable): Unit = ()
|
||||
def endGroup(name: String, result: TestResult.Value): Unit = {
|
||||
def endGroup(name: String, result: TestResult): Unit = {
|
||||
if (result == TestResult.Passed)
|
||||
succeeded(name) = System.currentTimeMillis
|
||||
}
|
||||
def doComplete(finalResult: TestResult.Value): Unit = {
|
||||
def doComplete(finalResult: TestResult): Unit = {
|
||||
TestStatus.write(succeeded, "Successful Tests", f)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package sbt.internal.testing
|
||||
|
||||
import sbt.testing.Status
|
||||
|
||||
import _root_.sjsonnew.{ deserializationError, serializationError, Builder, JsonFormat, Unbuilder }
|
||||
|
||||
trait StatusFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val StatusFormat: JsonFormat[Status] = new JsonFormat[Status] {
|
||||
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): Status = {
|
||||
jsOpt match {
|
||||
case Some(js) =>
|
||||
unbuilder.readString(js) match {
|
||||
case "Success" => Status.Success
|
||||
case "Error" => Status.Error
|
||||
case "Failure" => Status.Failure
|
||||
case "Skipped" => Status.Skipped
|
||||
case "Ignored" => Status.Ignored
|
||||
case "Canceled" => Status.Canceled
|
||||
case "Pending" => Status.Pending
|
||||
}
|
||||
case None =>
|
||||
deserializationError("Expected JsString but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: Status, builder: Builder[J]): Unit = {
|
||||
val str = obj match {
|
||||
case Status.Success => "Success"
|
||||
case Status.Error => "Error"
|
||||
case Status.Failure => "Failure"
|
||||
case Status.Skipped => "Skipped"
|
||||
case Status.Ignored => "Ignored"
|
||||
case Status.Canceled => "Canceled"
|
||||
case Status.Pending => "Pending"
|
||||
}
|
||||
builder.writeString(str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
package sbt
|
||||
package internal.testing
|
||||
|
||||
import testing.{ Logger => TLogger }
|
||||
import sbt.internal.util.{ ManagedLogger, BufferedAppender }
|
||||
import sbt.util.{ Level, LogExchange }
|
||||
import sbt.protocol.testing._
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
object TestLogger {
|
||||
import sbt.protocol.testing.codec.JsonProtocol._
|
||||
|
||||
private def generateName: String =
|
||||
"test-" + generateId.incrementAndGet
|
||||
private val generateId: AtomicInteger = new AtomicInteger
|
||||
private def generateBufferName: String =
|
||||
"testbuffer-" + generateBufferId.incrementAndGet
|
||||
private val generateBufferId: AtomicInteger = new AtomicInteger
|
||||
|
||||
final class PerTest private[sbt] (val log: ManagedLogger, val flush: () => Unit, val buffered: Boolean)
|
||||
|
||||
def make(global: ManagedLogger, perTest: TestDefinition => PerTest): TestLogger =
|
||||
{
|
||||
def makePerTest(tdef: TestDefinition): ContentLogger =
|
||||
{
|
||||
val per = perTest(tdef)
|
||||
val l0 = per.log
|
||||
val config = LogExchange.loggerConfig(l0.name)
|
||||
val as = config.getAppenders.asScala
|
||||
val buffs: List[BufferedAppender] = (as map {
|
||||
case (k, v) => BufferedAppender(generateBufferName, v)
|
||||
}).toList
|
||||
val newLog = LogExchange.logger(generateName, l0.channelName, l0.execId)
|
||||
LogExchange.bindLoggerAppenders(newLog.name, buffs map { x => (x, Level.Debug) })
|
||||
if (per.buffered) {
|
||||
buffs foreach { _.record() }
|
||||
}
|
||||
new ContentLogger(wrap(newLog), () => {
|
||||
buffs foreach { _.stopQuietly() }
|
||||
per.flush()
|
||||
})
|
||||
}
|
||||
val config = new TestLogging(wrap(global), global, makePerTest)
|
||||
new TestLogger(config)
|
||||
}
|
||||
|
||||
def wrap(logger: ManagedLogger): TLogger =
|
||||
new TLogger {
|
||||
def error(s: String) = log(Level.Error, TestStringEvent(s))
|
||||
def warn(s: String) = log(Level.Warn, TestStringEvent(s))
|
||||
def info(s: String) = log(Level.Info, TestStringEvent(s))
|
||||
def debug(s: String) = log(Level.Debug, TestStringEvent(s))
|
||||
def trace(t: Throwable) = logger.trace(t)
|
||||
private def log(level: Level.Value, event: TestStringEvent) = logger.logEvent(level, event)
|
||||
def ansiCodesSupported() = logger.ansiCodesSupported
|
||||
}
|
||||
|
||||
private[sbt] def toTestItemEvent(event: TestEvent): TestItemEvent =
|
||||
TestItemEvent(event.result, event.detail.toVector map { d =>
|
||||
TestItemDetail(
|
||||
d.fullyQualifiedName,
|
||||
d.status,
|
||||
d.duration match {
|
||||
case -1 => None
|
||||
case x => Some(x)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
final class TestLogging(
|
||||
val global: TLogger,
|
||||
val managed: ManagedLogger,
|
||||
val logTest: TestDefinition => ContentLogger
|
||||
)
|
||||
|
||||
class TestLogger(val logging: TestLogging) extends TestsListener {
|
||||
import TestLogger._
|
||||
import logging.{ global => log, logTest, managed }
|
||||
import sbt.protocol.testing.codec.JsonProtocol._
|
||||
|
||||
def startGroup(name: String): Unit =
|
||||
managed.logEvent(Level.Info, StartTestGroupEvent(name))
|
||||
def testEvent(event: TestEvent): Unit =
|
||||
managed.logEvent(Level.Info, toTestItemEvent(event))
|
||||
def endGroup(name: String, t: Throwable): Unit = {
|
||||
log.trace(t)
|
||||
log.error("Could not run test " + name + ": " + t.toString)
|
||||
managed.logEvent(Level.Info, EndTestGroupErrorEvent(
|
||||
name,
|
||||
t.getMessage + "\n" + t.getStackTrace.toList.mkString("\n")
|
||||
))
|
||||
}
|
||||
def endGroup(name: String, result: TestResult): Unit =
|
||||
managed.logEvent(Level.Info, EndTestGroupEvent(name, result))
|
||||
def doInit: Unit = managed.logEvent(Level.Info, TestInitEvent())
|
||||
/** called once, at end of test group. */
|
||||
def doComplete(finalResult: TestResult): Unit =
|
||||
managed.logEvent(Level.Info, TestCompleteEvent(finalResult))
|
||||
override def contentLogger(test: TestDefinition): Option[ContentLogger] = Some(logTest(test))
|
||||
}
|
||||
Loading…
Reference in New Issue