From b4bfb13c9c1cfb5e44bc7cfcf33ac107712afa47 Mon Sep 17 00:00:00 2001 From: EraKin575 Date: Tue, 9 Apr 2024 19:05:33 +0530 Subject: [PATCH 1/2] moved middleware to v2 Signed-off-by: EraKin575 --- .vscode/settings.json | 3 + common/pom.xml | 12 ++ .../java/io/keploy/utils/CoverageHandler.java | 185 ++++++++++++++++++ v2/pom.xml | 11 ++ .../io/keploy/servlet/KeployMiddleware.java | 184 +++++++++++++++++ 5 files changed, 395 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 common/src/main/java/io/keploy/utils/CoverageHandler.java create mode 100644 v2/src/main/java/io/keploy/servlet/KeployMiddleware.java diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..e0f15db2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "automatic" +} \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml index b9a3250b..3fe9771b 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -21,5 +21,17 @@ 1.0.0-SNAPSHOT compile + + + org.yaml + snakeyaml + 1.25 + + + + org.jacoco + org.jacoco.core + 0.7.6.201602180812 + \ No newline at end of file diff --git a/common/src/main/java/io/keploy/utils/CoverageHandler.java b/common/src/main/java/io/keploy/utils/CoverageHandler.java new file mode 100644 index 00000000..ab25fb31 --- /dev/null +++ b/common/src/main/java/io/keploy/utils/CoverageHandler.java @@ -0,0 +1,185 @@ +package io.keploy.utils; + +import java.io.File; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +import org.jacoco.core.analysis.Analyzer; +import org.jacoco.core.analysis.CoverageBuilder; +import org.jacoco.core.analysis.IClassCoverage; +import org.jacoco.core.analysis.ICounter; +import org.jacoco.core.tools.ExecFileLoader; +import org.jacoco.core.data.ExecutionDataWriter; +import org.jacoco.core.runtime.RemoteControlReader; +import org.jacoco.core.runtime.RemoteControlWriter; +import org.yaml.snakeyaml.DumperOptions; +import java.net.Socket; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.reader.UnicodeReader; + + + +public class CoverageHandler { + private static final String ADDRESS = "localhost"; + public static String Line_Path = ""; + + + private static final int PORT = 36320; + + public static void getCoverage(String keploy_test_id) throws IOException, InterruptedException { + + try { + execWriter(keploy_test_id); + } catch (IOException e) { + e.printStackTrace(); + } + + try { + execReader(keploy_test_id); + } catch (IOException e) { + e.printStackTrace(); // Example: print the stack trace + } + + } + +public static void execWriter(String keploy_test_id) throws IOException { + File directory = new File( + System.getProperty("user.dir") + "/target"); + File file = new File(directory, "jacoco-client" + keploy_test_id + ".exec"); +// File file = new File(directory, "jacoco-client.exec"); + + final FileOutputStream localFile = new FileOutputStream(file); + + final ExecutionDataWriter localWriter = new ExecutionDataWriter( + localFile); + + // Open a socket to the coverage agent: + final Socket socket = new Socket(InetAddress.getByName(ADDRESS), PORT); + final RemoteControlWriter writer = new RemoteControlWriter( + socket.getOutputStream()); + final RemoteControlReader reader = new RemoteControlReader( + socket.getInputStream()); + reader.setSessionInfoVisitor(localWriter); + reader.setExecutionDataVisitor(localWriter); + + // Send a dump command and read the response: + writer.visitDumpCommand(true, true); + if (!reader.read()) { + throw new IOException("Socket closed unexpectedly."); + } + + socket.close(); + localFile.close(); +} +private static void execReader(String keploy_test_id) throws IOException { + // Together with the original class definition we can calculate coverage + // information: + System.out.println("------------------------------------------"); + ExecFileLoader loader = new ExecFileLoader(); + + List> dataList = new ArrayList<>(); + // Load the coverage data file + File coverageFile = new File( + System.getProperty("user.dir") + + "/target/jacoco-client" + keploy_test_id + ".exec"); +// File coverageFile = new File( +// System.getProperty("user.dir") + +// "/target/jacoco-client.exec"); + loader.load(coverageFile); + File binDir = new File( + System.getProperty("user.dir")+ "/target/classes"); + final CoverageBuilder coverageBuilder = new CoverageBuilder(); + final Analyzer analyzer = new Analyzer(loader.getExecutionDataStore(), coverageBuilder); + analyzer.analyzeAll(binDir); + int x = 0; + Map> executedLinesByFile = new HashMap<>(); + + for (final IClassCoverage cc : coverageBuilder.getClasses()) { + // out.printf("Coverage of class %s%n", cc.getName()); + String ClassName = cc.getName(); // base64Encode(cc.getName()); + // System.out.println(cc.getMethods()); + java.util.Collection method = cc.getMethods(); + + cc.getInstructionCounter().getTotalCount(); + List ls = new ArrayList<>(); + for (int i = cc.getFirstLine(); i <= cc.getLastLine(); i++) { + // out.printf("Line %s: %s%n", Integer.valueOf(i), + // getColor(cc.getLine(i).getStatus())); + if (getColor(cc.getLine(i).getStatus()).equals("green")) { + Line_Path += ClassName + i + ","; + ls.add(i); + } + } + if (ls.size() != 0) { + executedLinesByFile.put(ClassName, ls); + } + + } + +// System.out.println("Line_Path: " + Line_Path); + + Map testData = new HashMap<>(); + testData.put("id", keploy_test_id); + // Map test1 = createTestData("test-1",testData); + testData.put("executedLinesByFile", executedLinesByFile); + + dataList.add(testData); + + List> existingData = readYamlFile("dedupData.yaml"); + // Append new data to the existing data + existingData.addAll(dataList); + + // Write data to YAML file + writeYamlFile(existingData, "dedupData.yaml"); +} +private static List> readYamlFile(String fileName) { + List> existingData = new ArrayList<>(); + + try (InputStream input = new FileInputStream(fileName); + UnicodeReader reader = new UnicodeReader(input)) { + + Yaml yaml = new Yaml(); + existingData = yaml.load(reader); + + } catch (IOException e) { + e.printStackTrace(); + } + + return existingData != null ? existingData : new ArrayList<>(); +} + + private static String getColor(final int status) { + switch (status) { + case ICounter.NOT_COVERED: + return "red"; + case ICounter.PARTLY_COVERED: + return "yellow"; + case ICounter.FULLY_COVERED: + return "green"; + } + return ""; + } + + + private static void writeYamlFile(List> dataList, String fileName) { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + + Yaml yaml = new Yaml(options); + + try (FileWriter writer = new FileWriter(fileName)) { + yaml.dump(dataList, writer); + System.out.println("Dedup YAML file updated successfully:- " + fileName); + } catch (IOException e) { + e.printStackTrace(); + } + }} diff --git a/v2/pom.xml b/v2/pom.xml index b898e81d..cbdec724 100644 --- a/v2/pom.xml +++ b/v2/pom.xml @@ -17,6 +17,11 @@ org.json json 20230618 + + + io.keploy + common + 1.0.0-SNAPSHOT com.google.code.gson @@ -25,6 +30,12 @@ compile + + + org.jacoco + org.jacoco.core + 0.8.7 + diff --git a/v2/src/main/java/io/keploy/servlet/KeployMiddleware.java b/v2/src/main/java/io/keploy/servlet/KeployMiddleware.java new file mode 100644 index 00000000..428b5907 --- /dev/null +++ b/v2/src/main/java/io/keploy/servlet/KeployMiddleware.java @@ -0,0 +1,184 @@ +package io.keploy.servlet; + +import io.grpc.netty.shaded.io.netty.util.internal.InternalThreadLocalMap; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jacoco.core.data.ExecutionDataWriter; +import org.jacoco.core.runtime.RemoteControlReader; +import org.jacoco.core.runtime.RemoteControlWriter; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import io.keploy.utils.CoverageHandler; + + +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +public class KeployMiddleware implements Filter { + + private final ExecutorService executorService = Executors.newFixedThreadPool(10); + public static int Lines_covered = 0; + public static int Branch_covered = 0; + public static int Lines_total = 0; + public static int Branch_total = 0; + public static int Methods_covered = 0; + public static int Methods_total = 0; + public static int Classes_covered = 0; + public static int Classes_total = 0; + public static String Line_Path = ""; + + private static final Logger logger = LogManager.getLogger(KeployMiddleware.class); + private static final String CROSS = new String(Character.toChars(0x274C)); + public static ArrayList stackTraceArr = new ArrayList<>(); + private static boolean EnableDedup = false; + public static AtomicInteger metCount = new AtomicInteger(0); + public static AtomicInteger reqCount = new AtomicInteger(0); + public static AtomicInteger cnt = new AtomicInteger(0); + // public static AtomicInteger linesCovered = new AtomicInteger(0); + + // private static final String DESTFILE = "jacoco-client.exec"; + + private static final String ADDRESS = "localhost"; + + private static final int PORT = 36320; + + @Override + public void init(FilterConfig filterConfig) { + logger.debug("Keploy Middleware initialized"); + + } + + private static final String SET_PLAIN_TEXT = "\033[0;0m"; + private static final String SET_BOLD_TEXT = "\033[0;1m"; + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + String keploy_test_id = request.getHeader("KEPLOY-TEST-ID"); + // logger.debug("KEPLOY-TEST-ID: {}", keploy_test_id); + filterChain.doFilter(request, response); + if (System.getenv("ENABLE_DEDUP") != null) { + String bool = System.getenv("ENABLE_DEDUP").trim(); + EnableDedup = bool.equals("true"); + } + // check if dedup is disabled then what should be the goal may be we can extract from header if dedup is enabled or not + if (keploy_test_id != null && EnableDedup) { + + // Run getCoverage in a separate thread +// Thread coverageThread = new Thread(() -> { + try { + CoverageHandler.getCoverage(keploy_test_id); + + } catch (InterruptedException | IOException e) { + throw new RuntimeException(e); + } +// }); + +// coverageThread.start(); +// try { +// Thread.sleep(500); +// } catch (InterruptedException e) { +// throw new RuntimeException(e); +// } + } + + } + + @Override + public void destroy() { + InternalThreadLocalMap.destroy(); + } + + public void execWriter(String keploy_test_id) throws IOException { + File directory = new File( + System.getProperty("user.dir") + "/target"); + File file = new File(directory, "jacoco-client" + keploy_test_id + ".exec"); +// File file = new File(directory, "jacoco-client.exec"); + + final FileOutputStream localFile = new FileOutputStream(file); + + final ExecutionDataWriter localWriter = new ExecutionDataWriter( + localFile); + + // Open a socket to the coverage agent: + final Socket socket = new Socket(InetAddress.getByName(ADDRESS), PORT); + final RemoteControlWriter writer = new RemoteControlWriter( + socket.getOutputStream()); + final RemoteControlReader reader = new RemoteControlReader( + socket.getInputStream()); + reader.setSessionInfoVisitor(localWriter); + reader.setExecutionDataVisitor(localWriter); + + // Send a dump command and read the response: + writer.visitDumpCommand(true, true); + if (!reader.read()) { + throw new IOException("Socket closed unexpectedly."); + } + + socket.close(); + localFile.close(); + } + + public synchronized void execWriter2(String keploy_test_id) throws IOException { + File directory = new File(System.getProperty("user.dir")+"/target"); + File file = new File(directory, "jacoco-client" + keploy_test_id + ".exec"); + + FileOutputStream localFile = null; + ExecutionDataWriter localWriter = null; + Socket socket = null; + RemoteControlWriter writer = null; + RemoteControlReader reader = null; + + try { + localFile = new FileOutputStream(file); + BufferedOutputStream bufferedLocalFile = new BufferedOutputStream(localFile); + localWriter = new ExecutionDataWriter(bufferedLocalFile); + socket = new Socket(InetAddress.getByName(ADDRESS), PORT); + writer = new RemoteControlWriter(socket.getOutputStream()); + reader = new RemoteControlReader(socket.getInputStream()); + + reader.setSessionInfoVisitor(localWriter); + reader.setExecutionDataVisitor(localWriter); + + // Send a dump command and read the response: + writer.visitDumpCommand(true, true); + + if (!reader.read()) { + throw new IOException("Socket closed unexpectedly."); + } + } finally { + // Close resources in a finally block to ensure they are closed even if an exception occurs + + if (socket != null && !socket.isClosed()) { + socket.close(); + } + + if (localFile != null) { + localFile.close(); + } + } + } + + public void shutdownExecutor() { + executorService.shutdown(); + } + + + + + public static String base64Encode(String input) { + byte[] encodedBytes = Base64.getEncoder().encode(input.getBytes()); + return new String(encodedBytes); + } + + +} \ No newline at end of file From 7657fbea6e12b5ab7cc11bb4d0046ea9bfc53c01 Mon Sep 17 00:00:00 2001 From: EraKin575 Date: Wed, 10 Apr 2024 11:32:05 +0530 Subject: [PATCH 2/2] modified versioning for jacoco Signed-off-by: EraKin575 --- common/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/pom.xml b/common/pom.xml index 3fe9771b..d28e3e0e 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -31,7 +31,7 @@ org.jacoco org.jacoco.core - 0.7.6.201602180812 + 0.8.7 \ No newline at end of file