Проблема с спецификацией/scalatest-взаимодействием в приложении Play

У меня проблема, которую я действительно не могу объяснить... Она изолирована в проекте в https://github.com/betehess/play-scalatest.

Когда я запускаю test, sbt задерживается на некоторое время, а затем выдает это исключение:

> test
[error] Uncaught exception when running tests: java.net.ConnectException: Connection timed out
Exception in thread "Thread-1" java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:196)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at java.net.SocketInputStream.read(SocketInputStream.java:210)
    at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2293)
    at java.io.ObjectInputStream$BlockDataInputStream.readBlockHeader(ObjectInputStream.java:2473)
    at java.io.ObjectInputStream$BlockDataInputStream.refill(ObjectInputStream.java:2543)
    at java.io.ObjectInputStream$BlockDataInputStream.skipBlockData(ObjectInputStream.java:2445)
    at java.io.ObjectInputStream.skipCustomData(ObjectInputStream.java:1941)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1620)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:500)
    at java.lang.Throwable.readObject(Throwable.java:914)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at sbt.React.react(ForkTests.scala:117)
    at sbt.ForkTests$$anonfun$mainTestTask$1$Acceptor$2$.run(ForkTests.scala:76)
    at java.lang.Thread.run(Thread.java:745)

Похоже, что sbt застревает в блокирующем вызове с разветвленной средой в https://github.com/sbt/sbt/blob/0.13.5/main/actions/src/main/scala/sbt/ForkTests.scala#L117.

Некоторые замечания:

  • Я запускаю Ubuntu 13.10 и Java HotSpot (TM) 64-бит "1.7.0_65"
  • Никто из моих коллег не может воспроизвести проблему на своих машинах...
  • проблема возникает только тогда, когда scalatest находится в пути к классам, даже если он не используется здесь.
  • проблема исчезает, если я не использую Pluggin PlayScala и явно добавляю specs2 как зависимость
  • проблема исчезает, если я перехожу к скалярной зависимости в основной build.sbt

Ответ 1

Наконец я узнал, что происходит.

Оказывается, что при правильных настройках sbt разветкит JVM для выполнения тестов и захочет связаться с ним. Как это делается, зависит от тестовой среды. В случае scalatest связь между этими двумя процессами будет осуществляться через сервер. scalatest просто связывает адрес и порт сервера, которые должны использоваться sbt. И это происходит там.

val array = Array(InetAddress.getLocalHost.getHostAddress, skeleton.port.toString)

Теперь прочитайте, что говорит javadoc для InetAddress # getLocalHost:

Возвращает адрес локального хоста. Это достигается путем извлечения имя хоста из системы, а затем разрешить это имя в InetAddress.

Я нахожусь в Linux. Мой локальный хост ( никогда localhost) заканчивается dopey. Теперь, по какой-то причине (я возился с моей сетью дома), мой /etc/hosts назначал фиктивный адрес dopey. Поэтому вместо 127.0.0.1, scalatest попытается открыть сокет на этом вымышленном сервере. И из-за где это происходит, вы не видите ничего полезного в stacktrace.

Я предполагаю, что целью всегда было использовать 127.0.0.1...