Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Add new methods according to new approach of keploy serve #159

Merged
merged 2 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions v2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,16 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- Include all resources in src/main/resources (default behavior) -->
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</build>

</project>
233 changes: 148 additions & 85 deletions v2/src/main/java/io.keploy.cli/KeployCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,27 @@
import org.apache.logging.log4j.Logger;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;

Check failure on line 9 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Unused import - java.io.FileInputStream. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:9:8: error: Unused import - java.io.FileInputStream. (com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck)
import java.io.FileOutputStream;

Check failure on line 10 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Unused import - java.io.FileOutputStream. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:10:8: error: Unused import - java.io.FileOutputStream. (com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck)
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;

Check failure on line 19 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Unused import - java.nio.file.Paths. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:19:8: error: Unused import - java.nio.file.Paths. (com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck)
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

Check failure on line 26 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Line is longer than 80 characters (found 112). Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:26:0: error: Line is longer than 80 characters (found 112). (com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck)

// Jacococli & JacocoAgent version: 0.8.8
public class KeployCLI {

private static final String GRAPHQL_ENDPOINT = "/query";
Expand All @@ -25,9 +35,11 @@

private static int serverPort = 6789;

private static Process kprocess;
private static long userCommandPid = 0;

Check failure on line 38 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:38:5: error: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocVariableCheck)

private static Thread kLogThread;
private static String jacocoCliPath = "";

Check failure on line 40 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:40:5: error: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocVariableCheck)

private static String jacocoAgentPath = "";

Check failure on line 42 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:42:5: error: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocVariableCheck)

public class GraphQLResponse {
Data data;
Expand All @@ -49,91 +61,151 @@
}
}


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 {

Check failure on line 70 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Missing a Javadoc comment. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:70:5: error: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck)

Check failure on line 70 in v2/src/main/java/io.keploy.cli/KeployCLI.java

View workflow job for this annotation

GitHub Actions / checkstyle linting

[checkstyle] reported by reviewdog 🐶 Name 'StartUserApplication' must match pattern '^[a-z][a-zA-Z0-9]*$'. Raw Output: /github/workspace/./v2/src/main/java/io.keploy.cli/KeployCLI.java:70:24: error: Name 'StartUserApplication' must match pattern '^[a-z][a-zA-Z0-9]*$'. (com.puppycrawl.tools.checkstyle.checks.naming.MethodNameCheck)

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
Expand Down Expand Up @@ -191,7 +263,6 @@
return null;
}


// Fetch the status of testSet
public static TestRunStatus FetchTestSetStatus(String testRunId) {

Expand All @@ -203,8 +274,7 @@

String payload = String.format(
"{ \"query\": \"{ testSetStatus(testRunId: \\\"%s\\\") { status } }\" }",
testRunId
);
testRunId);

conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
Expand Down Expand Up @@ -239,8 +309,7 @@
return null;
}


// Run a particular testSet
// Run a particular testSet
public static String RunTestSet(String testSetName) {
try {
HttpURLConnection conn = setHttpClient();
Expand All @@ -250,8 +319,7 @@

String payload = String.format(
"{ \"query\": \"mutation { runTestSet(testSet: \\\"%s\\\") { success testRunId message } }\" }",
testSetName
);
testSetName);

conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
Expand Down Expand Up @@ -279,7 +347,6 @@

}


private static boolean isSuccessfulResponse(HttpURLConnection conn) throws IOException {
int responseCode = conn.getResponseCode();
return (responseCode >= 200 && responseCode < 300);
Expand All @@ -296,9 +363,6 @@
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();
Expand All @@ -324,7 +388,7 @@
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();
Expand Down Expand Up @@ -357,4 +421,3 @@
return Integer.parseInt(processName.split("@")[0]);
}
}

Binary file added v2/src/main/resources/jacocoagent.jar
Binary file not shown.
Binary file added v2/src/main/resources/jacococli.jar
Binary file not shown.
Loading