Skip to content

Commit

Permalink
[PExplicit] Adds running mvn test and github ci action
Browse files Browse the repository at this point in the history
  • Loading branch information
aman-goel committed Apr 9, 2024
1 parent 505d222 commit a4a7c94
Show file tree
Hide file tree
Showing 5 changed files with 517 additions and 2 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/pexplicit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# This workflow will build and test PExplicit, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: PExplicit on Ubuntu

on: [push, pull_request]

jobs:
PExplicit-Build-And-Test-Ubuntu:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 8.0.x
- name: Set up JDK
uses: actions/setup-java@v1
with:
java-version: 17
- name: Cache Maven packages
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build PExplicit
working-directory: Src/PRuntimes/PExplicitRuntime
run: ./scripts/build.sh
- name: Test PExplicit
working-directory: Src/PRuntimes/PExplicitRuntime
run: mvn test
2 changes: 0 additions & 2 deletions Src/PRuntimes/PExplicitRuntime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,9 @@
<configuration>
<systemPropertyVariables>
<propertyName>java.library.path</propertyName>
<mode/>
<timeout/>
<schedules/>
<max.steps/>
<pexplicit.args/>
</systemPropertyVariables>
<systemProperties>
<property>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package pexplicit;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.appender.OutputStreamAppender;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.layout.PatternLayout;
import pexplicit.runtime.logger.Log4JConfig;

/**
* Represents the logger for mvn test
*/
public class PExplicitTestLogger {
static Logger log = null;
static LoggerContext context = null;

public static void Initialize(String outputFolder) {
log = Log4JConfig.getContext().getLogger(pexplicit.PExplicitTestLogger.class.getName());
org.apache.logging.log4j.core.Logger coreLogger =
(org.apache.logging.log4j.core.Logger) LogManager.getLogger(pexplicit.PExplicitTestLogger.class.getName());
context = coreLogger.getContext();

try {
// get new file name
Date date = new Date();
String fileName = outputFolder + "/test-" + date + ".log";
File file = new File(fileName);
file.getParentFile().mkdirs();
file.createNewFile();

// Define new file printer
FileOutputStream fout = new FileOutputStream(fileName, false);

PatternLayout layout = Log4JConfig.getPatternLayout();
Appender fileAppender =
OutputStreamAppender.createAppender(layout, null, fout, fileName, false, true);
ConsoleAppender consoleAppender = ConsoleAppender.createDefaultAppenderForLayout(layout);
fileAppender.start();
consoleAppender.start();

context.getConfiguration().addLoggerAppender(coreLogger, fileAppender);
context.getConfiguration().addLoggerAppender(coreLogger, consoleAppender);
} catch (IOException e) {
System.out.println("Failed to set printer to the PSymTestLogger!!");
}
}

public static void disable() {
Configurator.setLevel(pexplicit.PExplicitTestLogger.class.getName(), Level.OFF);
}

public static void enable() {
Configurator.setLevel(pexplicit.PExplicitTestLogger.class.getName(), Level.ALL);
}

public static void log(String message) {
log.info(message);
}

public static void warn(String message) {
log.warn(message);
}

public static void error(String message) {
log.error(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package pexplicit;

import java.io.*;
import java.nio.file.Paths;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;

public class TestCaseExecutor {
private static int testCounter = 0;

/**
* @param testCasePaths paths to test case; only accepts list of p files
* @return 0 = successful, 1 = compile error, 2 = dynamic error
*/
static int runTestCase(
List<String> testCasePaths,
String testCasePathPrefix,
String runArgs,
String mainOutputDirectory,
int expected) {
int resultCode;

testCounter++;

// Invoke the P compiler to compile the test Case
boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
String compilerDirectory = "../../../Bld/Drops/Release/Binaries/net8.0/p.dll";

assert testCasePaths.stream().allMatch(p -> p.contains(testCasePathPrefix));
String testName = testCasePathPrefix.substring(testCasePathPrefix.lastIndexOf("/") + 1);
if (testName.isEmpty()) {
List<String> testCaseRelPaths =
testCasePaths.stream()
.map(p -> p.substring(p.indexOf(testCasePathPrefix) + testCasePathPrefix.length()))
.collect(Collectors.toList());
testName = Paths.get(testCaseRelPaths.get(0)).getFileName().toString();
}
testName = testName.replaceAll("_", "");
testName = testName.replaceAll("-", "");

String outputDirectory = mainOutputDirectory + "/" + testName;
recreateDirectory(outputDirectory);
PExplicitTestLogger.log(String.format(" [%d] %s", testCounter, testName));

List<String> pTestCasePaths =
testCasePaths.stream().filter(p -> p.contains(".p")).collect(Collectors.toList());
String testCasePathsString = String.join(" ", pTestCasePaths);

Process process;
try {
String pCompileCommand =
String.format(
"dotnet %s compile --mode explicit --projname %s --outdir %s --pfiles %s",
compilerDirectory, testName, outputDirectory, testCasePathsString);
PExplicitTestLogger.log(" compiling");
process = buildCompileProcess(pCompileCommand, outputDirectory);

StreamGobbler errorStreamGobbler =
new StreamGobbler(process.getErrorStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(errorStreamGobbler);
StreamGobbler streamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
resultCode = process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
resultCode = -1;
}

String pathToJar =
outputDirectory + "/PExplicit/target/" + testName + "-jar-with-dependencies.jar";

File jarFile = new File(pathToJar);
if (!jarFile.exists() || jarFile.isDirectory()) {
resultCode = 1;
}

if (resultCode != 0) {
PExplicitTestLogger.log(" compile-fail");
if (resultCode != expected) {
PExplicitTestLogger.log(
String.format(
" unexpected result for %s (expected: %d, got: %d)",
testCasePathPrefix, expected, resultCode));
}
return resultCode;
}

// Next, try to dynamically load and compile this file
try {
int seed = Math.abs((new Random()).nextInt());
String runJarCommand =
String.format(
"dotnet %s check %s --mode explicit --outdir %s --seed %d %s",
compilerDirectory, pathToJar, outputDirectory, seed, runArgs);
PExplicitTestLogger.log(String.format(" running with seed %d", seed));
process = buildRunProcess(runJarCommand, outputDirectory);

StreamGobbler streamGobbler =
new StreamGobbler(process.getErrorStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
StreamGobbler outstreamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(outstreamGobbler);
resultCode = process.waitFor();

if (resultCode == 0) {
PExplicitTestLogger.log(" ok");
} else if (resultCode == 2) {
PExplicitTestLogger.log(" bug");
} else if (resultCode == 3) {
PExplicitTestLogger.log(" timeout");
} else if (resultCode == 4) {
PExplicitTestLogger.log(" memout");
} else {
PExplicitTestLogger.log(" error");
}
} catch (IOException | InterruptedException e) {
PExplicitTestLogger.error(" fail");
e.printStackTrace();
resultCode = -1;
}
if (resultCode != expected) {
PExplicitTestLogger.log(
String.format(
" unexpected result for %s (expected: %d, got: %d)",
testCasePathPrefix, expected, resultCode));
}
return resultCode;
}

/**
* A method to build a new Process object for given compile command.
*
* @param cmd Jar command as string
* @param outFolder output folder
* @return A new process for the given task
* @throws IOException
*/
private static Process buildCompileProcess(String cmd, String outFolder) throws IOException {
ProcessBuilder builder = new ProcessBuilder(cmd.split(" "));
File outFile = new File(outFolder + "/compile.out");
outFile.getParentFile().mkdirs();
outFile.createNewFile();
builder.redirectOutput(outFile);

File errFile = new File(outFolder + "/compiler.err");
errFile.getParentFile().mkdirs();
errFile.createNewFile();
builder.redirectError(errFile);
return builder.start();
}

/**
* A method to build a new Process object for given run command.
*
* @param cmd Jar command as string
* @param outFolder output folder
* @return A new process for the given task
* @throws IOException
*/
private static Process buildRunProcess(String cmd, String outFolder) throws IOException {
ProcessBuilder builder = new ProcessBuilder(cmd.split("\\s+"));
File outFile = new File(outFolder + "/run.out");
outFile.getParentFile().mkdirs();
outFile.createNewFile();
builder.redirectOutput(outFile);

File errFile = new File(outFolder + "/run.err");
errFile.getParentFile().mkdirs();
errFile.createNewFile();
builder.redirectError(errFile);
return builder.start();
}

private static void recreateDirectory(String dir) {
try {
File f = new File(dir);
if (f.isDirectory()) {
FileUtils.cleanDirectory(f); // clean out directory (this is optional -- but good know)
FileUtils.forceDelete(f); // delete directory
}
FileUtils.forceMkdir(f); // create directory
} catch (IOException e) {
e.printStackTrace();
}
}

private static class StreamGobbler implements Runnable {
private final InputStream inputStream;
private final Consumer<String> consumer;

StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
this.inputStream = inputStream;
this.consumer = consumer;
}

@Override
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer);
}
}
}
Loading

0 comments on commit a4a7c94

Please sign in to comment.