From 27e93601b57e037f2ba71de5683530591e249bf7 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Fri, 24 Nov 2017 12:43:50 -0800 Subject: [PATCH] Add warning for slow hostname lookups on OS X I spent a lot of time debugging why it took 5 seconds to run tests each time. It turns out that if the hostname is not set explicitly on os x, then getaddrinfo takes 5 seconds to try (and fail) to resolve the dns entry for the localhostname. This is easily fixed by setting the hostname, but it is not at all easy to figure out that a slow hostname lookup is the reason why tests are slow to start. I don't know if this is a common issue on other platforms, so only issue the warning on OS X. --- main/src/main/scala/sbt/internal/Load.scala | 4 +++- .../sbt/plugins/JUnitXmlReportPlugin.scala | 2 +- .../scala/sbt/JUnitXmlTestsListener.scala | 22 ++++++++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/main/src/main/scala/sbt/internal/Load.scala b/main/src/main/scala/sbt/internal/Load.scala index 8a316bbc1..c496a7f32 100755 --- a/main/src/main/scala/sbt/internal/Load.scala +++ b/main/src/main/scala/sbt/internal/Load.scala @@ -1039,7 +1039,9 @@ private[sbt] object Load { // Grab all the settings we already loaded from sbt files def settings(files: Seq[File]): Seq[Setting[_]] = { if (files.nonEmpty) - log.info(s"${files.map(_.getName).mkString(s"Loading settings for project ${p.id} from ", ",", " ...")}") + log.info( + s"${files.map(_.getName).mkString(s"Loading settings for project ${p.id} from ", ",", " ...")}" + ) for { file <- files config <- (memoSettings get file).toSeq diff --git a/main/src/main/scala/sbt/plugins/JUnitXmlReportPlugin.scala b/main/src/main/scala/sbt/plugins/JUnitXmlReportPlugin.scala index b65324be7..232265d68 100644 --- a/main/src/main/scala/sbt/plugins/JUnitXmlReportPlugin.scala +++ b/main/src/main/scala/sbt/plugins/JUnitXmlReportPlugin.scala @@ -30,6 +30,6 @@ object JUnitXmlReportPlugin extends AutoPlugin { // It might be a good idea to derive this setting into specific test scopes. override lazy val projectSettings: Seq[Setting[_]] = Seq( - testListeners += new JUnitXmlTestsListener(target.value.getAbsolutePath) + testListeners += new JUnitXmlTestsListener(target.value.getAbsolutePath, streams.value.log) ) } diff --git a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala index 9344305f5..a59e44ee7 100644 --- a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala +++ b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala @@ -13,8 +13,10 @@ import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit import java.util.Hashtable +import java.util.concurrent.TimeUnit.NANOSECONDS import scala.collection.mutable.ListBuffer +import scala.util.Properties import scala.xml.{ Elem, Node => XNode, XML } import testing.{ Event => TEvent, @@ -23,6 +25,7 @@ import testing.{ OptionalThrowable, TestSelector } +import util.Logger import sbt.protocol.testing.TestResult /** @@ -30,14 +33,27 @@ import sbt.protocol.testing.TestResult * report format. * @param outputDir path to the dir in which a folder with results is generated */ -class JUnitXmlTestsListener(val outputDir: String) extends TestsListener { +class JUnitXmlTestsListener(val outputDir: String, logger: Logger) extends TestsListener { + // This constructor is for binary compatibility with older versions of sbt. + def this(outputDir: String) = this(outputDir, null) /**Current hostname so we know which machine executed the tests*/ - val hostname = - try InetAddress.getLocalHost.getHostName + val hostname = { + val start = System.nanoTime + 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( + s"Getting the hostname $name was slow (${elapsed / 1.0e6} ms). " + + "This is likely because the computer's hostname is not set. You can set the " + + "hostname with the command: scutil --set HostName $(scutil --get LocalHostName)." + ) + } + name + } /**The dir in which we put all result files. Is equal to the given dir + "/test-reports"*/ val targetDir = new File(outputDir + "/test-reports/")