Cube Standalone and JaCoCo

discussion

#1

Cube Standalone is a mode in Arquillian Cube which instead of deploying a WAR file inside a running Docker container and run the tests inside the container, it starts an already created docker image with WAR file copied inside.
Then test is executed as client, outside the container. Because of this you can run tests against that docker image. The problem is that when running this tests you have no way to get code coverage of business code since it runs inside an already created Docker image.

But from the point of view of Cube we could do some kind of magic to allow run JaCoCo inside the container and then get the results.

The problem is that any idea I get for modifying the deployed WAR file to do Code Coverage Offline finds a problem:

  • To get the war file to enrich with JaCoCo I need to run that container to get the war file, and this means that I need to get the war file to client (no problem), modify the war (no problem) copy again inside the container (no problem) but since container was started the war file was already deployed so this means that this is a redeployment of same war file but enriched, and every application service might have different behaviour.
  • Use a Dockerfile 1. The problem again is that we cannot get the WAR file without having container up.
  • Use Dockerfile 2. Create a Dockerfile based on the image given by user, copy the JaCoCo zip and add in JavaOpts env var the javaagent thing.

It seems that third option might be a candidate to work, but do you have any other approach/idea on how to face the problem?

Ty


#2

To expand on your option 3; could you not mount a volume wth ‘docker run -v…’ (using the image from the user) to capture the JaCoCo output file and use JAVA_OPTS to add the javaagent parameters required?

I am just exploring this approach for my current project.


#3

So I have working prototype of this but it’s very ‘Heath Robinson’ and patched together with toothpaste and string. Here’s the list of problems I hit:

  • Getting the Jacoco dump file: By default this is triggered by the JVM shutdown, with Cube the JVM is not shutdown the Docker container is. So no jacoco.exec
  • Getting the Jacoco dump via TCP: using JacocoToGo lets you dump coverage data via TCP. However this requires that your agent is still running and Surefire only runs your server for the duration of the tests and then shutsdown. So you get either ‘connection refused’ or ‘broken pipe’ errors when you try to retrieve the Jacoco data
  • Getting the Jacoco data format to match: JacocoToGo was compiled against a pre v0.7.4 of Jacoco and they changed the binary stream format. So you need to use Jacoco v0.7.4.x or you get ‘broken pipe’ errors

What did eventually work was:

  1. Starting the target Docker image manually before the tests; pass JAVA_OPTS=${jacoco.agent} via -e, mount jacoco.jar with -v and jacoco.exec with -v
  2. In arquillian.xml allow connect to running container (and leave running!) with connectionMode=STARTORCONNECTANDLEAVE
  3. Trigger the tcp dump with JacocoToGo (because your server is still running this now works!)
  4. Make an offering to any god(s) you believe in
  5. Process report and view code coverage :smiley:

Clearly this can be radically improved, my prototype uses fixed IPs for the TCP comms and all sorts of other non-portable hacks. I’m going to look into using Arquillian Enrichers and use cubeController and/or dockerClient to better control the start/stop of the Cube container(s) and get the dynamic IP of the container

This would all be a LOT simpler if the maven-jacoco-agent allowed the triggering of a dump to file via a maven goal. Maybe Arquillian-Jacoco could consider something?