From 4b928f16c280592dfe67969509cae0e7e0bd14b1 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 17 Jan 2022 02:27:44 -0500 Subject: [PATCH] Port testing --- build.sbt | 4 +- .../testing/codec/TestItemEventFormats.scala | 9 +- .../testing/codec/TestMessageFormats.scala | 12 ++- .../scala/sbt/JUnitXmlTestsListener.scala | 87 +++++++++---------- .../src/main/scala/sbt/TestFramework.scala | 37 ++++---- .../main/scala/sbt/TestReportListener.scala | 8 +- .../sbt/internal/testing/TestLogger.scala | 4 +- 7 files changed, 93 insertions(+), 68 deletions(-) diff --git a/build.sbt b/build.sbt index 9c73c4874..b78da0a68 100644 --- a/build.sbt +++ b/build.sbt @@ -191,6 +191,7 @@ lazy val sbtRoot: Project = (project in file(".")) utilCache, taskProj, stdTaskProj, + testingProj, ) .settings( minimalSettings, @@ -472,7 +473,8 @@ lazy val testingProj = (project in file("testing")) scalaXml.value, testInterface, launcherInterface, - sjsonNewScalaJson.value + sjsonNewScalaJson.value, + sjsonNewCore.value, ), Compile / scalacOptions += "-Ywarn-unused:-locals,-explicits,-privates", Compile / managedSourceDirectories += diff --git a/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestItemEventFormats.scala b/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestItemEventFormats.scala index d6a8af553..dd16c4c62 100644 --- a/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestItemEventFormats.scala +++ b/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestItemEventFormats.scala @@ -5,7 +5,14 @@ // DO NOT EDIT MANUALLY package sbt.protocol.testing.codec import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } -trait TestItemEventFormats { self: sbt.protocol.testing.codec.TestResultFormats with sbt.protocol.testing.codec.TestItemDetailFormats with sjsonnew.BasicJsonProtocol => +trait TestItemEventFormats { self: sbt.protocol.testing.codec.TestResultFormats with + sbt.protocol.testing.codec.TestItemDetailFormats with + sbt.internal.testing.StatusFormats with + sbt.protocol.testing.codec.TestCompleteEventFormats with + sbt.protocol.testing.codec.StartTestGroupEventFormats with + sbt.protocol.testing.codec.EndTestGroupErrorEventFormats with + sbt.protocol.testing.codec.TestInitEventFormats 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 { diff --git a/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestMessageFormats.scala b/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestMessageFormats.scala index 13534855d..bff9329d7 100644 --- a/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestMessageFormats.scala +++ b/testing/src/main/contraband-scala/sbt/protocol/testing/codec/TestMessageFormats.scala @@ -6,6 +6,16 @@ package sbt.protocol.testing.codec import _root_.sjsonnew.JsonFormat -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 => +trait TestMessageFormats { self: sjsonnew.BasicJsonProtocol with + sbt.internal.testing.StatusFormats 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") } diff --git a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala index ebe66bfcd..8c07dc070 100644 --- a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala +++ b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala @@ -29,9 +29,9 @@ import util.Logger import sbt.protocol.testing.TestResult /** - * A tests listener that outputs the results it receives in junit xml - * report format. - * @param targetDir directory in which test reports are generated + * A tests listener that outputs the results it receives in junit xml report format. + * @param targetDir + * directory in which test reports are generated */ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logger: Logger) extends TestsListener { @@ -45,13 +45,14 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg @deprecated("Provided for binary compatibility: please use `targetDir` instead", "1.6.0") def outputDir: String = targetDir.getParent - /**Current hostname so we know which machine executed the tests*/ + /** Current hostname so we know which machine executed the tests */ val hostname: String = { val start = System.nanoTime - val name = try InetAddress.getLocalHost.getHostName - catch { - case _: IOException => "localhost" - } + val name = + try InetAddress.getLocalHost.getHostName + catch { + case _: IOException => "localhost" + } val elapsed = System.nanoTime - start if ((NANOSECONDS.toSeconds(elapsed) >= 4) && Properties.isMac && logger != null) { logger.warn( @@ -63,7 +64,7 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg name } - /**all system properties as XML*/ + /** all system properties as XML */ val properties: Elem = { @@ -80,23 +81,22 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg /** - * Gathers data for one Test Suite. We map test groups to TestSuites. - * Each TestSuite gets its own output file. + * Gathers data for one Test Suite. We map test groups to TestSuites. Each TestSuite gets its own + * output file. */ class TestSuite(val name: String, timestamp: LocalDateTime) { def this(name: String) = this(name, LocalDateTime.now()) val events: ListBuffer[TEvent] = new ListBuffer() - /**Adds one test result to this suite.*/ + /** Adds one test result to this suite. */ def addEvent(e: TEvent): ListBuffer[TEvent] = events += e /** Returns the number of tests of each state for the specified. */ def count(status: TStatus) = events.count(_.status == status) /** - * Stops the time measuring and emits the XML for - * All tests collected so far. + * Stops the time measuring and emits the XML for All tests collected so far. */ def stop(): Elem = { val duration = events.map(_.duration()).sum @@ -112,7 +112,9 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg val classnameRegex = s"^($name|${name.split('.').last})\\.?".r val result = - nested.testName() - case other => s"(It is not a test it is a ${other.getClass.getCanonicalName})" + case other => s"(It is not a test it is a ${other.getClass.getCanonicalName})" } } time={(e.duration() / 1000.0).toString}> { @@ -155,7 +157,7 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg {trace} - case TStatus.Failure => + case TStatus.Failure => case TStatus.Ignored | TStatus.Skipped | TStatus.Pending => case _ => {} } @@ -171,7 +173,7 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg } } - /**The currently running test suite*/ + /** The currently running test suite */ private val testSuite = new InheritableThreadLocal[Option[TestSuite]] { override def initialValue(): Option[TestSuite] = None } @@ -179,7 +181,7 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg private def withTestSuite[T](f: TestSuite => T): T = testSuite.get().map(f).getOrElse(sys.error("no test suite")) - /**Creates the output Dir*/ + /** Creates the output Dir */ override def doInit(): Unit = { val _ = targetDir.mkdirs() } @@ -197,34 +199,29 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg } /** - * called for each class or equivalent grouping - * We map one group to one Testsuite, so for each Group - * we create [[https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd JUnit XML file]], and looks like this: + * called for each class or equivalent grouping We map one group to one Testsuite, so for each + * Group we create + * [[https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd JUnit XML file]], and looks + * like this: * - * - * - * - * - * ... - * - * - * ... stack ... - * - * - * - * ...stack... - * - * - * - * + * ... + * + * ... stack + * ... ...stack... + * */ override def endGroup(name: String, t: Throwable): Unit = { // create our own event to record the error val event: TEvent = new TEvent { def fullyQualifiedName = name - //def description = - //"Throwable escaped the test run of '%s'".format(name) - def duration = -1 + // def description = + // "Throwable escaped the test run of '%s'".format(name) + def duration() = -1 def status = TStatus.Error def fingerprint = null def selector = null @@ -235,8 +232,8 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg } /** - * 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. + * 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): Unit = { writeSuite() @@ -265,9 +262,9 @@ class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logg testSuite.remove() } - /**Does nothing, as we write each file after a suite is done.*/ + /** Does nothing, as we write each file after a suite is done. */ override def doComplete(finalResult: TestResult): Unit = {} - /**Returns None*/ + /** Returns None */ override def contentLogger(test: TestDefinition): Option[ContentLogger] = None } diff --git a/testing/src/main/scala/sbt/TestFramework.scala b/testing/src/main/scala/sbt/TestFramework.scala index bd20829ed..08bd78e90 100644 --- a/testing/src/main/scala/sbt/TestFramework.scala +++ b/testing/src/main/scala/sbt/TestFramework.scala @@ -179,14 +179,13 @@ object TestFramework { def getFingerprints(framework: Framework): Seq[Fingerprint] = framework.getClass.getMethod("fingerprints").invoke(framework) match { case fingerprints: Array[Fingerprint] => fingerprints.toList - case _ => sys.error("Could not call 'fingerprints' on framework " + framework) + case _ => sys.error("Could not call 'fingerprints' on framework " + framework) } 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) } + 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 { @@ -221,9 +220,16 @@ object TestFramework { if (mappedTests.isEmpty) (() => (), Vector(), _ => () => ()) else - createTestTasks(testLoader, runners.map { - case (tf, r) => (frameworks(tf), new TestRunner(r, listeners, log)) - }, mappedTests, tests, log, listeners) + createTestTasks( + testLoader, + runners.map { case (tf, r) => + (frameworks(tf), new TestRunner(r, listeners, log)) + }, + mappedTests, + tests, + log, + listeners + ) } private[this] def order( @@ -270,14 +276,13 @@ object TestFramework { val startTask = foreachListenerSafe(_.doInit()) val testTasks = - Map(tests.toSeq.flatMap { - case (framework, testDefinitions) => - val runner = runners(framework) - val testTasks = withContextLoader(loader) { runner.tasks(testDefinitions) } - for (testTask <- testTasks) yield { - val taskDef = testTask.taskDef - (taskDef.fullyQualifiedName, createTestFunction(loader, taskDef, runner, testTask)) - } + Map(tests.toSeq.flatMap { case (framework, testDefinitions) => + val runner = runners(framework) + val testTasks = withContextLoader(loader) { runner.tasks(testDefinitions) } + for (testTask <- testTasks) yield { + val taskDef = testTask.taskDef + (taskDef.fullyQualifiedName, createTestFunction(loader, taskDef, runner, testTask)) + } }: _*) val endTask = (result: TestResult) => foreachListenerSafe(_.doComplete(result)) diff --git a/testing/src/main/scala/sbt/TestReportListener.scala b/testing/src/main/scala/sbt/TestReportListener.scala index 08df6c415..0e73d21e1 100644 --- a/testing/src/main/scala/sbt/TestReportListener.scala +++ b/testing/src/main/scala/sbt/TestReportListener.scala @@ -41,7 +41,9 @@ trait TestsListener extends TestReportListener { } -/** Provides the overall `result` of a group of tests (a suite) and test counts for each result type. */ +/** + * Provides the overall `result` of a group of tests (a suite) and test counts for each result type. + */ final class SuiteResult( val result: TestResult, val passedCount: Int, @@ -98,7 +100,9 @@ final class SuiteResult( object SuiteResult { - /** Computes the overall result and counts for a suite with individual test results in `events`. */ + /** + * Computes the overall result and counts for a suite with individual test results in `events`. + */ def apply(events: Seq[TEvent]): SuiteResult = { def count(status: TStatus) = events.count(_.status == status) new SuiteResult( diff --git a/testing/src/main/scala/sbt/internal/testing/TestLogger.scala b/testing/src/main/scala/sbt/internal/testing/TestLogger.scala index 0e7bd1437..3ce2be998 100644 --- a/testing/src/main/scala/sbt/internal/testing/TestLogger.scala +++ b/testing/src/main/scala/sbt/internal/testing/TestLogger.scala @@ -18,8 +18,8 @@ object TestLogger { import sbt.protocol.testing.codec.JsonProtocol._ implicit val testStringEventShowLines: ShowLines[TestStringEvent] = - ShowLines[TestStringEvent]({ - case a: TestStringEvent => List(a.value) + ShowLines[TestStringEvent]({ case a: TestStringEvent => + List(a.value) }) private def generateName: String = "test-" + generateId.incrementAndGet