Missing coverage of some services when all services sends execution data to same tcp/ip SocketServer

87 views
Skip to first unread message

Vijay Nanekar

unread,
May 13, 2019, 6:02:19 AM5/13/19
to JaCoCo and EclEmma Users
Hello,

All our micro-services are sending execution data to the same socket server and on the same port. These are the Jacoco agent parameters we are setting. 

java -javaagent:$PWD/coverage/jacocoagent.jar=output=tcpclient,destfile=$PWD/jacoco-server.exec,includes=*,address=1XX.XX.XX.XX,port=6300


We are running given ExecutionDataServer.java class from address=1XX.XX.XX.XX machine which listens for incoming execution data.

First, Could you please tell me, is it a good practice to collect execution data from multiple services to the same server socket?

If yes, Then are we missed anything in below ExecutionDataServer class? as we are missing coverage from some of the services.

When we start services, we get "Retrieving execution Data for session: <SERVICE_NAME>" log in ExecutionDataServer's class output for all services. But then we are not getting this log statement again even though we hit the code of that service.

Please help.

public final class ExecutionDataServer {

    private static String DESTFILE = "jacoco-server.exec";

    private static String ADDRESS = "localhost";

    private static int PORT = 6300;

    /**
     * Start the server as a standalone program.
     * 
     * @param args
     * @throws IOException
     */
    public static void main(final String[] args) throws IOException {
        final ExecutionDataWriter fileWriter = new ExecutionDataWriter(new FileOutputStream(DESTFILE));
        final ServerSocket server = new ServerSocket(PORT, 0, InetAddress.getByName(ADDRESS));
        while (true) {
            try {
                final Handler handler = new Handler(server.accept(), fileWriter);
                new Thread(handler).start();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println(e.getMessage());
            }
        }
    }

    private static class Handler implements Runnable, ISessionInfoVisitor, IExecutionDataVisitor {

        private final Socket socket;

        private final RemoteControlReader reader;

        private final RemoteControlWriter writer;

        private final ExecutionDataWriter fileWriter;

        Handler(final Socket socket, final ExecutionDataWriter fileWriter) throws IOException {
            this.socket = socket;
            this.fileWriter = fileWriter;

            // Just send a valid header:
            writer = new RemoteControlWriter(socket.getOutputStream());

            reader = new RemoteControlReader(socket.getInputStream());
            reader.setSessionInfoVisitor(this);
            reader.setExecutionDataVisitor(this);
        }

        public void run() {
            try {
                writer.visitDumpCommand(true, false);
                while (reader.read()) {
                }
                socket.close();
                synchronized (fileWriter) {
                    fileWriter.flush();
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }

        public void visitSessionInfo(final SessionInfo info) {
            System.out.printf("Retrieving execution Data for session: %s%n", info.getId());
            synchronized (fileWriter) {
                fileWriter.visitSessionInfo(info);
            }
        }

        public void visitClassExecution(final ExecutionData data) {
            synchronized (fileWriter) {
                fileWriter.visitClassExecution(data);
            }
        }
    }

    private ExecutionDataServer() {
    }
}


Marc Hoffmann

unread,
May 13, 2019, 6:19:03 AM5/13/19
to jac...@googlegroups.com
Hi,

technical it should be possible to use the same server socket for multiple clients at the same time. Our example code should also be robust for concurrent access. But I personally never tested this aspect. Can you please send the broken exec file? The position of the broken bytes might give a hint.

By default JaCoCo only dumps execution data when you properly shut down a JVM. It has not notion about “micro service” or “hit”. Therefore I’m surprised that you get the the log entry when starting your services.

BTW, the destfile parameter is not used when you configure the agent with output=tcpclient

Regards,
-marc


--
You received this message because you are subscribed to the Google Groups "JaCoCo and EclEmma Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jacoco+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jacoco/34854dc9-1a80-4019-bfd2-8b0571d9a993%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Vijay Nanekar

unread,
May 13, 2019, 6:40:51 AM5/13/19
to JaCoCo and EclEmma Users
Thank you Marc.

Yes, destfile parameter is not required here as we are using output=tcpclient. 

In the case of output=tcpclient, I think we don't need to shutdown JVM to collect data. We request execution data from ExecutionDataServer class using statement "writer.visitDumpCommand(true, false);". Please correct me if I am wrong.

Please find link to shared .exec file.



Thanks,
Vijay
To unsubscribe from this group and stop receiving emails from it, send an email to jac...@googlegroups.com.

Marc Hoffmann

unread,
May 13, 2019, 6:48:33 AM5/13/19
to jac...@googlegroups.com
Hi Vijay,

ok, I see, you added "writer.visitDumpCommand(true, false);” This means when the JVM starts and the agent connects to the ExecutionDataServer the dump request is immediately triggered. At this point in time no application code has been executed. You probably need a smarter version of ExecutionDataServer which requests dumps once your tests are finished.

Regards,
-marc


To unsubscribe from this group and stop receiving emails from it, send an email to jacoco+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jacoco/3b09bd80-951b-4d11-a3e6-8cdf9b171d35%40googlegroups.com.

Vijay Nanekar

unread,
May 13, 2019, 6:52:26 AM5/13/19
to jac...@googlegroups.com
Hello Marc,

Yes, but I execute this in infinite loop which will continuously request to dump execution data.

Thanks & Regards
Vijay

Evgeny Mandrikov

unread,
May 13, 2019, 6:52:52 AM5/13/19
to JaCoCo and EclEmma Users
You call visitDumpCommand only once immediately after incoming connect, which means that following happens

client JVM starts and JaCoCo agent immediately connects to your server
server receives incoming connection and immediately requests coverage, whereas your code wasn't yet executed in client JVM
after that client JVM executes your code

Marc Hoffmann

unread,
May 13, 2019, 8:04:48 AM5/13/19
to jac...@googlegroups.com
Hi Vijay,

I just checked the file you provided: It’s a perfectly valid exec file.

You can check exec files yourself using the JaCoCo command line tools:

java -jar jacococli.jar execinfo <yourexecfile>

Regards,
-marc

Evgeny Mandrikov

unread,
May 13, 2019, 9:35:51 AM5/13/19
to JaCoCo and EclEmma Users


On Monday, May 13, 2019 at 12:52:26 PM UTC+2, Vijay Nanekar wrote:

Yes, but I execute this in infinite loop which will continuously request to dump execution data.

According to the code that you shown:

Your infinite loop "while (true)" in method main handles connections from different clients - "server.accept" waits for new client, then new thread is created, then loop continues.
Each such thread performs "visitDumpCommand" once and only once at its start, then your loop "while (reader.read())" reads data and waits for more data.
Note that each client JVM connects only once at start of JaCoCo agent, so
client JVM starts, JaCoCo agent connects to your server, immediately receives request, and responds by writing  data which was collected only till this moment of time,
in absence of other requests, client JVM will write data next time only at the termination, using your terminology - only when "service" stops.

Hope now clear how code of your server works.

Thus in order to receive full data
either you gracefully stop your client JVMs at the end of your tests,
or as Marc said - you need to find a way for your server to request data at the end of your tests.

We can't say how to change code of this server, because there are many options - maybe you want to receive data from all connected clients when you terminate server, or maybe using some other trigger, or maybe you want to receive data periodically, etc.


Regards,
Evgeny

Vijay Nanekar

unread,
May 13, 2019, 10:08:13 AM5/13/19
to JaCoCo and EclEmma Users
It's clear now. Thanks a lot, Evgeny and Marc. Yes, I will update ExecutionDataServer code as per our need.

Thanks,
Vijay

kanna shravan

unread,
Jun 7, 2019, 10:38:18 AM6/7/19
to JaCoCo and EclEmma Users
Hi Vijay, i do have a small task on jacoco and i need to enable code coverage for automated gunit tests. can you help me that ? 

Vijay Nanekar

unread,
Jun 9, 2019, 3:21:50 AM6/9/19
to jac...@googlegroups.com
Sure. I will help whatever is possible from my side.

-Vijay

To unsubscribe from this group and stop receiving emails from it, send an email to jacoco+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jacoco/a69ec41f-4f54-4400-ad9d-0e585c134780%40googlegroups.com.
Reply all
Reply to author
Forward
This conversation is locked
You cannot reply and perform actions on locked conversations.
0 new messages