Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

specs/scalatest interaction issue in Play app

I am having a problem I really can't explain... It is in isolation in the project at https://github.com/betehess/play-scalatest.

When I run test, sbt gets stuck for a while and then throws this exception:

> 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)

Looks like sbt gets stuck in a blocking call with the forked environment at https://github.com/sbt/sbt/blob/0.13.5/main/actions/src/main/scala/sbt/ForkTests.scala#L117.

Some remarks:

  • I run Ubuntu 13.10 and Java HotSpot(TM) 64-Bit "1.7.0_65"
  • none of my colleagues can reproduce the problem on their machines...
  • the problem happens only when scalatest is on the classpath, even if not used here
  • the problem goes away if I don't use the PlayScala pluggin and add specs2 explicitly as a dependency
  • the problem goes away if I move the scalatest dependency into the main build.sbt
like image 496
betehess Avatar asked Sep 11 '14 19:09

betehess


1 Answers

I finally found out what was happening.

It turns out that under the right settings, sbt will fork the JVM to execute the tests, and will want to communicate with it. How this is done is up to the test framework. In the case of scalatest, the communication between the two processes will be done through a server. scalatest just communicates the server address and port that have to be used by sbt. And this is happening there.

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

Now, go read what the javadoc says for InetAddress#getLocalHost:

Returns the address of the local host. This is achieved by retrieving the name of the host from the system, then resolving that name into an InetAddress.

I am on Linux. My local host (which is never localhost) ends up being dopey. Now, for some reason (I was messing with my network at home), my /etc/hosts was assigning a bogus address to dopey. So instead of something like 127.0.0.1, scalatest would try to open a socket on this fictional server. And because of where this is happening, you don't see anything helpful in the stacktrace.

My guess is that the intention was always to use 127.0.0.1...

like image 79
betehess Avatar answered Nov 07 '22 19:11

betehess