diff --git a/v2/pom.xml b/v2/pom.xml
index ff1c6865..afcc05aa 100644
--- a/v2/pom.xml
+++ b/v2/pom.xml
@@ -34,4 +34,16 @@
UTF-8
+
+
+
+ src/main/resources
+
+
+ **/*
+
+
+
+
+
\ No newline at end of file
diff --git a/v2/src/main/java/io.keploy.cli/KeployCLI.java b/v2/src/main/java/io.keploy.cli/KeployCLI.java
index 08e7646a..aef7301a 100644
--- a/v2/src/main/java/io.keploy.cli/KeployCLI.java
+++ b/v2/src/main/java/io.keploy.cli/KeployCLI.java
@@ -5,17 +5,27 @@
import org.apache.logging.log4j.Logger;
import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.net.HttpURLConnection;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+//FOR CLI CODE COVERAGE REFERENCE: https://dzone.com/articles/code-coverage-report-generator-for-java-projects-a
+// Jacococli & JacocoAgent version: 0.8.8
public class KeployCLI {
private static final String GRAPHQL_ENDPOINT = "/query";
@@ -25,9 +35,11 @@ public class KeployCLI {
private static int serverPort = 6789;
- private static Process kprocess;
+ private static long userCommandPid = 0;
- private static Thread kLogThread;
+ private static String jacocoCliPath = "";
+
+ private static String jacocoAgentPath = "";
public class GraphQLResponse {
Data data;
@@ -49,91 +61,151 @@ public class RunTestSetResponse {
}
}
-
public enum TestRunStatus {
RUNNING,
PASSED,
FAILED
}
-// public static void main(String[] args) throws IOException, InterruptedException {
-// }
-
-
- // Run Keploy server
- public static void RunKeployServer(long pid, int delay, String testPath, int port) throws InterruptedException, IOException {
- // Registering a shutdown hook
- Runtime.getRuntime().addShutdownHook(new Thread(() -> {
- System.out.println("\nShutdown hook executed!");
- kprocess.destroy();
- try {
- Thread.sleep(1000);
- kLogThread.join();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
+ public static void StartUserApplication(String runCmd) throws IOException {
+
+ runCmd = attachJacocoAgent(runCmd);
+
+ // Split the runCmd string into command parts
+ String[] command = runCmd.split(" ");
+
+ // Start the command using ProcessBuilder
+ ProcessBuilder processBuilder = new ProcessBuilder(command);
+ processBuilder.redirectErrorStream(true);
+ Process process = processBuilder.start();
+
+ // Get the PID of the process
+ userCommandPid = getProcessId(process);
+
+ // Start a thread to log the output of the process
+ Thread logThread = new Thread(() -> logProcessOutput(process));
+ logThread.start();
+ }
+
+ private static String attachJacocoAgent(String cmd) {
+ String resourcePath = "jacocoagent.jar"; // Relative path in the JAR file
+
+ try (InputStream is = KeployCLI.class.getClassLoader().getResourceAsStream(resourcePath)) {
+ if (is == null) {
+ throw new IllegalStateException("jacocoagent.jar not found in resources");
}
- }));
-
-
-// String password = "keploy@123"; // Ensure this isn't hardcoded in production code!
-// String commandString = "echo '" + password + "' | sudo -S /usr/local/bin/keploy serve --pid=" + pid + " -p=" + testPath + " -d=" + delay + " --port=" + port;
-// String[] command = {
-// commandString
-// };
-
- // Construct the keploy command
- String[] command = {
- "sudo",
- "-S",
- "/usr/local/bin/keploy",
- "serve",
- "--pid=" + pid,
- "-p=" + testPath,
- "-d=" + delay,
- "--port=" + port,
- "--language=java"
- };
-
-
- if (port != 0) {
- serverPort = port;
+
+ Path tempFile = Files.createTempFile("jacocoagent", ".jar");
+
+ // Using Files.copy for robust file copying
+ Files.copy(is, tempFile, StandardCopyOption.REPLACE_EXISTING);
+ is.close();
+ String agentString = "-javaagent:" + tempFile.toAbsolutePath()
+ + "=address=localhost,port=36320,destfile=coverage.exec,output=tcpserver";
+
+ jacocoAgentPath = tempFile.toAbsolutePath().toString();
+ return cmd.replaceFirst("java", "java " + agentString);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new IllegalStateException("Error setting up JaCoCo agent", e);
}
+ }
+
+ public static void FindCoverage(String testSet) throws IOException, InterruptedException {
+ String dest = "target/" + testSet;
+ String runCmd = "java -jar " + getJacococliPath() + " dump --address localhost --port 36320 --destfile "
+ + dest + ".exec";
- // Start the keploy command
+
+ // Split the runCmd string into command parts
+ String[] command = runCmd.split(" ");
+
+ // Start the command using ProcessBuilder
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true);
- kprocess = processBuilder.start();
-
-// // When running without root user
-// String password = "keploy@123";
-// try (OutputStream os = kprocess.getOutputStream()) {
-// os.write((password + "\n").getBytes());
-// os.flush();
-// }
-
- // Read the output in real-time
-
- Thread logThread = new Thread(() -> {
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(kprocess.getInputStream()))) {
- String line;
- while (kprocess.isAlive() && (line = reader.readLine()) != null) {
- System.out.println(line);
- }
- } catch (IOException e) {
- // Since the stream might get closed due to process termination,
- // we can handle this specific error more gracefully
- if (!"Stream closed".equals(e.getMessage())) {
- e.printStackTrace();
- }
+ Process process = processBuilder.start();
+
+ // Start a thread to log the output of the process
+ Thread logThread = new Thread(() -> logProcessOutput(process));
+ logThread.start();
+ }
+
+ private static String getJacococliPath() {
+ String resourcePath = "jacococli.jar"; // Relative path in the JAR file
+
+ try (InputStream is = KeployCLI.class.getClassLoader().getResourceAsStream(resourcePath)) {
+ if (is == null) {
+ throw new IllegalStateException("jacococli.jar not found in resources");
}
- });
+ Path tempFile = Files.createTempFile("jacococli", ".jar");
- logThread.start();
+ // Using Files.copy for robust file copying
+ Files.copy(is, tempFile, StandardCopyOption.REPLACE_EXISTING);
+ is.close();
+ jacocoCliPath = tempFile.toAbsolutePath().toString();
+ return jacocoCliPath;
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw new IllegalStateException("Error setting up JacocoCli", e);
+ }
+ }
+
+ public static void StopUserApplication() {
+ deleteJacocoFiles();
+ killProcessesAndTheirChildren((int) userCommandPid);
+ }
+
+ private static void deleteJacocoFiles() {
+ deleteFile(jacocoAgentPath);
+ deleteFile(jacocoCliPath);
+ }
+
+ private static boolean deleteFile(String filePath) {
+ File file = new File(filePath);
+
+ // Check if the file exists
+ if (!file.exists()) {
+ System.out.println("File not found: " + filePath);
+ return false;
+ }
+
+ // Attempt to delete the file
+ if (file.delete()) {
+ logger.debug("File deleted successfully:",filePath);
+ // System.out.println("File deleted successfully: " + filePath);
+ return true;
+ } else {
+ System.out.println("Failed to delete the file: " + filePath);
+ return false;
+ }
+ }
- kLogThread = logThread;
- // Wait for the command to finish and get its exit code
-// int exitCode = process.waitFor();
+ private static long getProcessId(Process process) {
+ // Java 9 and later
+ if (process.getClass().getName().equals("java.lang.ProcessImpl")) {
+ return process.pid();
+ }
+
+ // Java 8 and earlier
+ try {
+ java.lang.reflect.Field f = process.getClass().getDeclaredField("pid");
+ f.setAccessible(true);
+ return f.getLong(process);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException("Unable to get process ID", e);
+ }
+ }
+
+ private static void logProcessOutput(Process process) {
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ System.out.println(line);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
// Set the HTTP client
@@ -191,7 +263,6 @@ public static String[] FetchTestSets() {
return null;
}
-
// Fetch the status of testSet
public static TestRunStatus FetchTestSetStatus(String testRunId) {
@@ -203,8 +274,7 @@ public static TestRunStatus FetchTestSetStatus(String testRunId) {
String payload = String.format(
"{ \"query\": \"{ testSetStatus(testRunId: \\\"%s\\\") { status } }\" }",
- testRunId
- );
+ testRunId);
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
@@ -239,8 +309,7 @@ public static TestRunStatus FetchTestSetStatus(String testRunId) {
return null;
}
-
- // Run a particular testSet
+ // Run a particular testSet
public static String RunTestSet(String testSetName) {
try {
HttpURLConnection conn = setHttpClient();
@@ -250,8 +319,7 @@ public static String RunTestSet(String testSetName) {
String payload = String.format(
"{ \"query\": \"mutation { runTestSet(testSet: \\\"%s\\\") { success testRunId message } }\" }",
- testSetName
- );
+ testSetName);
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
@@ -279,7 +347,6 @@ public static String RunTestSet(String testSetName) {
}
-
private static boolean isSuccessfulResponse(HttpURLConnection conn) throws IOException {
int responseCode = conn.getResponseCode();
return (responseCode >= 200 && responseCode < 300);
@@ -296,9 +363,6 @@ private static String getSimulateResponseBody(HttpURLConnection conn) throws IOE
return content.toString();
}
- public static void StopKeployServer() {
- killProcessOnPort(serverPort);
- }
public static void killProcessOnPort(int port) {
try {
Process process = new ProcessBuilder("sh", "-c", "lsof -t -i:" + port).start();
@@ -324,7 +388,7 @@ public static void killProcessesAndTheirChildren(int parentPID) {
for (int childPID : pids) {
if (childPID != getCurrentPid()) {
try {
- new ProcessBuilder("sudo", "kill", "-9", String.valueOf(childPID)).start();
+ new ProcessBuilder("sudo", "kill", "-15", String.valueOf(childPID)).start();
logger.debug("Killed child process " + childPID);
} catch (Exception e) {
e.printStackTrace();
@@ -357,4 +421,3 @@ private static int getCurrentPid() {
return Integer.parseInt(processName.split("@")[0]);
}
}
-
diff --git a/v2/src/main/resources/jacocoagent.jar b/v2/src/main/resources/jacocoagent.jar
new file mode 100644
index 00000000..7799b3c0
Binary files /dev/null and b/v2/src/main/resources/jacocoagent.jar differ
diff --git a/v2/src/main/resources/jacococli.jar b/v2/src/main/resources/jacococli.jar
new file mode 100644
index 00000000..27a66d56
Binary files /dev/null and b/v2/src/main/resources/jacococli.jar differ