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

v3.4.0 #90

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
9 changes: 1 addition & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>cambio.simulator</groupId>
<artifactId>misim</artifactId>
<version>3.3.4-SNAPSHOT</version>
<version>3.4.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>MiSim Simulator</name>
Expand All @@ -28,7 +28,6 @@

<junit.version>5.9.1</junit.version>
<mockito.version>4.8.0</mockito.version>
<system-lambda.version>1.2.1</system-lambda.version>
</properties>

<scm>
Expand Down Expand Up @@ -139,12 +138,6 @@
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>${system-lambda.version}</version>
<scope>test</scope>
</dependency>
<dependency> <!-- this may needs to be moved to default scope if needed elsewhere than the tests -->
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
Expand Down
139 changes: 68 additions & 71 deletions src/main/java/cambio/simulator/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
*/
public final class Main {

/**
* Exit codes for the program. See {@link #main(String[])} for meanings.
*/
public static final class ExitCodes {
public static final int SUCCESSFUL_RUN = 0;
public static final int EXCEPTION_DURING_ARGUMENT_PARSING = 1;
public static final int EXCEPTION_DURING_PARSING = 2;
public static final int EXCEPTION_DURING_SIMULATION = 16;
public static final int EXCEPTION_UNKNOWN = 512;
}

/**
* Main entry point of the program. Pass "-h" to see arguments.
*
Expand Down Expand Up @@ -64,47 +75,9 @@ public final class Main {
* @see #runExperiment(ExperimentStartupConfig)
*/
public static void main(final String[] args) {
int returnCode = runExperiment(args);

ExperimentStartupConfig startupConfig = parseArgsToConfig(args);

try {

//---------------------------------------Experiment execution-----------------------------------------------

Experiment experiment = runExperiment(args);

//-------------------------------------------Error handling-------------------------------------------------

if (experiment.hasError()) {
System.out.println("[INFO] Simulation failed.");
System.exit(16);
} else {
System.out.println("[INFO] Simulation finished successfully.");
writeCommandLineReport((MiSimModel) experiment.getModel());
System.exit(0);
}
} catch (ParsingException | JsonParseException e) {
if (startupConfig.debugOutputOn()) {
e.printStackTrace();
} else {
System.out.println("[ERROR] " + e.getMessage());
}
System.exit(2);
} catch (Exception e) {
//In tests, System.exit throws an exception with a private type from the
//"com.github.stefanbirkner.systemlambda" package. This exception is supposed to be
//thrown up to top level to be detected by a test and therefore is not handled here.
//TODO: this should (and will have to be with later java versions) be removed
if (e.getClass().getPackage().getName().equals("com.github.stefanbirkner.systemlambda")) {
throw e;
}

if (startupConfig.debugOutputOn()) {
e.printStackTrace();
}

System.exit(512);
}
System.exit(returnCode);
}

/**
Expand All @@ -129,71 +102,95 @@ public static void mainVarargs(final String... args) {
}


private static @NotNull ExperimentStartupConfig parseArgsToConfig(String[] args) {
private static @NotNull ExperimentStartupConfig parseArgsToConfig(String[] args) throws ParseException {
// trim whitespaces from arguments to please apache cli
String[] argsTrimmed = Arrays.stream(args).map(String::trim).toArray(String[]::new);
try {
return CLI.parseArguments(ExperimentStartupConfig.class, argsTrimmed);
} catch (ParseException e) {
System.err.println("[ERROR] " + e.getMessage());
System.exit(1);
}
return null;
}


private static @NotNull Experiment runExperiment(String[] args) {

ExperimentStartupConfig startupConfig = parseArgsToConfig(args);

Experiment experiment = runExperiment(startupConfig);

return experiment;

return CLI.parseArguments(ExperimentStartupConfig.class, argsTrimmed);
}

/**
* Starts an experiment, and uses the given string as cli arguments (splits on spaces). Use spaces only to separate
* arguments and not inside a value.
*
* @param cliString the cli argument string
* @param cliString the cli argument string to parse. See {@link ExperimentStartupConfig} or --help for details.
* @return the exit code of the experiment, see {@link #main(String[])} for meanings.
* @see #main(String[])
* @see #mainVarargs(String...)
* @see #runExperiment(ExperimentStartupConfig)
*/
public static @NotNull Experiment runExperiment(final String cliString) {
public static int runExperiment(final String cliString) {
return runExperiment(cliString.replaceAll("\\s*", " ").split(" "));
}


/**
* Starts an experiment, and uses the given string as cli arguments. See {@link ExperimentStartupConfig} or --help
* for details.
*
* @param args the cli arguments to parse. See {@link ExperimentStartupConfig} for options.
* @return the exit code of the experiment, see {@link #main(String[])} for meanings.
*/
public static int runExperiment(String[] args) {
ExperimentStartupConfig startupConfig;

try {
startupConfig = parseArgsToConfig(args);
} catch (ParseException e) {
System.err.println("[ERROR] " + e.getMessage());
return ExitCodes.EXCEPTION_DURING_ARGUMENT_PARSING;
}
return runExperiment(startupConfig);
}


/**
* Starts an experiment with the given {@link ExperimentStartupConfig}.
*
* @param startupConfig the experiment startup configuration
* @return the exit code of the experiment, see {@link #main(String[])} for meanings.
* @see #runExperiment(String)
* @see #main(String[])
* @see #mainVarargs(String...)
*/
public static @NotNull Experiment runExperiment(final ExperimentStartupConfig startupConfig) {
Experiment experiment = new ExperimentCreator().createSimulationExperiment(startupConfig);
System.out.printf("[INFO] Starting simulation at approximately %s%n", java.time.LocalDateTime.now());
experiment.start();
experiment.finish();
public static int runExperiment(final ExperimentStartupConfig startupConfig) {
boolean isDebugOutputOn = startupConfig.debugOutputOn();
try {

Experiment experiment = new ExperimentCreator().createSimulationExperiment(startupConfig);
System.out.printf("[INFO] Starting simulation at approximately %s%n", java.time.LocalDateTime.now());
experiment.start();
experiment.finish();

RNGStorage.reset();
RNGStorage.reset(); //TODO: this should happen first

return experiment;

if (experiment.hasError()) {
System.out.println("[INFO] Simulation failed.");
return ExitCodes.EXCEPTION_DURING_SIMULATION;
}

System.out.println("[INFO] Simulation finished successfully.");
writeCommandLineReport((MiSimModel) experiment.getModel());
return ExitCodes.SUCCESSFUL_RUN;

} catch (ParsingException | JsonParseException e) {
Util.printExceptionMessage(e, isDebugOutputOn);
return ExitCodes.EXCEPTION_DURING_PARSING;
} catch (Exception e) {
Util.printExceptionMessage(e, isDebugOutputOn);
return ExitCodes.EXCEPTION_UNKNOWN;
}
}

private static void writeCommandLineReport(MiSimModel model) {
ExperimentMetaData metaData = model.getExperimentMetaData();
System.out.println("\n*** MiSim Report ***");
System.out.println("Simulation of Architecture: "
+ metaData.getArchitectureDescriptionLocation().getAbsolutePath());
+ metaData.getArchitectureDescriptionLocation().getAbsolutePath());
System.out.println("Executed Experiment: "
+ metaData.getExperimentDescriptionLocation().getAbsolutePath());
+ metaData.getExperimentDescriptionLocation().getAbsolutePath());
System.out.println("Report Location: "
+ metaData.getReportLocation().toAbsolutePath());
+ metaData.getReportLocation().toAbsolutePath());
System.out.println("Setup took: " + Util.timeFormat(metaData.getSetupExecutionDuration()));
System.out.println("Experiment took: " + Util.timeFormat(metaData.getExperimentExecutionDuration()));
System.out.println("Execution took: " + Util.timeFormat(metaData.getExecutionDuration()));
Expand Down
21 changes: 19 additions & 2 deletions src/main/java/cambio/simulator/misc/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ public static void injectField(String fieldName, @NotNull Object object, Object
if (field == null) {
assert object.getClass() != null;
throw new NoSuchFieldException(
String.format("Could not find find field %s on type %s or its super-classes.", fieldName,
object.getClass().getName()));
String.format("Could not find find field %s on type %s or its super-classes.", fieldName,
object.getClass().getName()));
}

field.setAccessible(true);
Expand All @@ -165,4 +165,21 @@ public static Field[] getAllFields(Class<?> clazz) {
}
return list.toArray(new Field[0]);
}

/**
* Prints the message of an exception to the console. If debug output is enabled, the stacktrace is also printed.
*
* @param e the exception
* @param isDebugOutputOn whether the stacktrace should be printed
*/
public static void printExceptionMessage(Exception e, boolean isDebugOutputOn) {
System.out.println("[ERROR] " + e.getMessage());
if (isDebugOutputOn) {
e.printStackTrace();
}
}

public static void printExceptionMessage(Exception e) {
printExceptionMessage(e, false);
}
}
15 changes: 7 additions & 8 deletions src/test/java/cambio/simulator/test/TestBase.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package cambio.simulator.test;

import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.File;
Expand Down Expand Up @@ -64,13 +63,13 @@ public Pair<MiSimModel, TestExperiment> getConnectedMockModel(File architecture,

protected void runSimulationCheckExit(int expectedExitCode, File arch, File exp, String... additionalArgs) {
try {
int code = catchSystemExit(() -> {
String[] fileLocations = new String[] {"-a", arch.getAbsolutePath(), "-e", exp.getAbsolutePath(), "-d"};
String[] allArgs = new String[additionalArgs.length + fileLocations.length];
System.arraycopy(fileLocations, 0, allArgs, 0, fileLocations.length);
System.arraycopy(additionalArgs, 0, allArgs, fileLocations.length, additionalArgs.length);
Main.main(allArgs);
});
String[] fileLocations = new String[]{"-a", arch.getAbsolutePath(), "-e", exp.getAbsolutePath(), "-d"};
String[] allArgs = new String[additionalArgs.length + fileLocations.length];
System.arraycopy(fileLocations, 0, allArgs, 0, fileLocations.length);
System.arraycopy(additionalArgs, 0, allArgs, fileLocations.length, additionalArgs.length);
int code = Main.runExperiment(allArgs);

System.out.println("Test exited with code: " + code);
assertEquals(expectedExitCode, code);
} catch (Exception e) {
Assertions.fail("Simulation failed.", e);
Expand Down
Loading