Skip to content

Commit cb7a961

Browse files
committed
Merge pull request #106 from tmc-langs/master
Refactored ExerciseRunners
2 parents 5f34f1b + 5f8a06a commit cb7a961

File tree

6 files changed

+143
-129
lines changed

6 files changed

+143
-129
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
package fi.helsinki.cs.tmc.data;
22

3+
import java.util.ArrayList;
34
import java.util.List;
45

56
public class TestRunResult {
67
private final List<TestCaseResult> testCaseResults;
8+
private final boolean compilationSucceeded;
79

810
public TestRunResult(List<TestCaseResult> testCaseResults) {
11+
this.compilationSucceeded = true;
912
this.testCaseResults = testCaseResults;
1013
}
1114

15+
public TestRunResult(boolean compilationSucceeded) {
16+
this.compilationSucceeded = compilationSucceeded;
17+
this.testCaseResults = new ArrayList<TestCaseResult>();
18+
}
19+
20+
public TestRunResult(List<TestCaseResult> testCaseResults, boolean compilationSucceeded) {
21+
this.testCaseResults = testCaseResults;
22+
this.compilationSucceeded = compilationSucceeded;
23+
}
24+
1225
public List<TestCaseResult> getTestCaseResults() {
1326
return testCaseResults;
1427
}
28+
29+
public boolean getCompilationSuccess() {
30+
return compilationSucceeded;
31+
}
1532
}

tmc-plugin/src/fi/helsinki/cs/tmc/runners/AntExerciseRunner.java

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,46 +27,63 @@
2727
import org.openide.filesystems.FileUtil;
2828
import org.openide.windows.InputOutput;
2929

30+
3031
public class AntExerciseRunner extends AbstractJavaExerciseRunner {
32+
3133
private static final Logger log = Logger.getLogger(AntExerciseRunner.class.getName());
34+
private static final Integer SUCCESS = 0;
3235

3336
@Override
34-
public Callable<Integer> getCompilingTask(TmcProjectInfo projectInfo) {
37+
public Callable<TestRunResult> getTestRunningTask(final TmcProjectInfo projectInfo) {
38+
return new Callable<TestRunResult>() {
39+
@Override
40+
public TestRunResult call() throws Exception {
41+
if (compileProject(projectInfo) == SUCCESS) {
42+
log.log(Level.INFO, "Compile success for project {0}", projectInfo.toString());
43+
return runTests(projectInfo);
44+
} else {
45+
return new TestRunResult(false);
46+
}
47+
}
48+
};
49+
}
50+
51+
protected int compileProject(TmcProjectInfo projectInfo) {
52+
log.info("Starting compile");
3553
Project project = projectInfo.getProject();
3654
FileObject buildScript = project.getProjectDirectory().getFileObject("build.xml");
55+
3756
if (buildScript == null) {
3857
throw new RuntimeException("Project has no build.xml");
3958
}
59+
4060
ExecutorTask task;
61+
4162
try {
4263
task = ActionUtils.runTarget(buildScript, new String[]{"compile-test"}, null);
43-
return executorTaskToCallable(task);
4464
} catch (IOException ex) {
4565
throw ExceptionUtils.toRuntimeException(ex);
4666
}
67+
68+
return task.result();
4769
}
4870

49-
@Override
50-
public Callable<TestRunResult> getTestRunningTask(final TmcProjectInfo projectInfo) {
51-
return new Callable<TestRunResult>() {
52-
@Override
53-
public TestRunResult call() throws UserVisibleException, IOException, InterruptedException, ExecutionException {
54-
FileObject testDir = findTestDir(projectInfo);
55-
if (testDir == null) {
56-
throw new UserVisibleException("No test directory in project");
57-
}
71+
protected TestRunResult runTests(final TmcProjectInfo projectInfo) throws UserVisibleException, IOException, InterruptedException, ExecutionException {
5872

59-
List<TestMethod> tests = findProjectTests(projectInfo, testDir);
73+
FileObject testDir = findTestDir(projectInfo);
74+
if (testDir == null) {
75+
throw new UserVisibleException("No test directory in project");
76+
}
6077

61-
File tempFile;
62-
tempFile = File.createTempFile("tmc_test_results", ".txt");
63-
try {
64-
return runTests(projectInfo, testDir, tests, tempFile);
65-
} finally {
66-
tempFile.delete();
67-
}
68-
}
69-
};
78+
List<TestMethod> tests = findProjectTests(projectInfo, testDir);
79+
80+
File tempFile;
81+
tempFile = File.createTempFile("tmc_test_results", ".txt");
82+
try {
83+
return runTests(projectInfo, testDir, tests, tempFile);
84+
} finally {
85+
tempFile.delete();
86+
}
7087
}
7188

7289
private TestRunResult runTests(final TmcProjectInfo projectInfo, FileObject testDir, List<TestMethod> testMethods, File tempFile) throws UserVisibleException {
@@ -118,7 +135,11 @@ private TestRunResult runTests(final TmcProjectInfo projectInfo, FileObject test
118135
throw ex;
119136
} catch (UserVisibleException ex) {
120137
throw ex;
121-
} catch (Throwable t) {
138+
} catch (InterruptedException t) {
139+
throw new UserVisibleException("Failed to run tests", t);
140+
} catch (ExecutionException t) {
141+
throw new UserVisibleException("Failed to run tests", t);
142+
} catch (IOException t) {
122143
throw new UserVisibleException("Failed to run tests", t);
123144
}
124145
}

tmc-plugin/src/fi/helsinki/cs/tmc/runners/ExerciseRunner.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
import fi.helsinki.cs.tmc.model.TmcProjectInfo;
55
import java.util.concurrent.Callable;
66

7+
/**
8+
* ExerciseRunner for implementing runner tasks
9+
*/
710
public interface ExerciseRunner {
8-
public abstract Callable<Integer> getCompilingTask(TmcProjectInfo projectInfo);
9-
1011
public abstract Callable<TestRunResult> getTestRunningTask(TmcProjectInfo projectInfo);
1112
}

tmc-plugin/src/fi/helsinki/cs/tmc/runners/MakefileExerciseRunner.java

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@
44
import fi.helsinki.cs.tmc.data.TestRunResult;
55
import fi.helsinki.cs.tmc.model.TmcProjectInfo;
66
import fi.helsinki.cs.tmc.model.UserVisibleException;
7-
import fi.helsinki.cs.tmc.utilities.BgTask;
8-
import fi.helsinki.cs.tmc.utilities.BgTaskListener;
97
import fi.helsinki.cs.tmc.utilities.process.ProcessResult;
108
import fi.helsinki.cs.tmc.utilities.process.ProcessRunner;
119
import java.io.File;
1210
import java.io.IOException;
1311
import java.util.Arrays;
1412
import java.util.concurrent.Callable;
1513
import java.util.logging.Level;
16-
import static java.util.logging.Level.INFO;
17-
import static java.util.logging.Level.WARNING;
1814
import java.util.logging.Logger;
1915
import org.netbeans.api.project.Project;
2016
import org.openide.filesystems.FileObject;
@@ -26,52 +22,48 @@ public class MakefileExerciseRunner extends AbstractExerciseRunner {
2622
private static final Logger log = Logger.getLogger(MakefileExerciseRunner.class.getName());
2723

2824
@Override
29-
public Callable<Integer> getCompilingTask(TmcProjectInfo projectInfo) {
30-
log.log(Level.INFO, "Compiling project {0}", projectInfo.getProjectName());
31-
Project project = projectInfo.getProject();
32-
FileObject makeFile = project.getProjectDirectory().getFileObject("Makefile");
33-
File workDir = projectInfo.getProjectDirAsFile();
34-
35-
if (makeFile == null) {
36-
log.log(INFO, "Project has no Makefile");
37-
throw new RuntimeException("Project has no Makefile");
38-
}
39-
String[] command = {"make", "test"};
40-
25+
public Callable<TestRunResult> getTestRunningTask(final TmcProjectInfo projectInfo) {
4126
final InputOutput io = IOProvider.getDefault().getIO(projectInfo.getProjectName(), false);
42-
final ProcessRunner runner = new ProcessRunner(command, workDir, io);
43-
return new Callable<Integer>() {
27+
28+
return new Callable<TestRunResult>() {
4429
@Override
45-
public Integer call() throws Exception {
30+
public TestRunResult call() throws Exception {
31+
log.log(Level.INFO, "Compiling project {0}", projectInfo.getProjectName());
32+
Project project = projectInfo.getProject();
33+
FileObject makeFile = project.getProjectDirectory().getFileObject("Makefile");
34+
35+
if (makeFile == null) {
36+
log.info("Project has no Makefile");
37+
throw new RuntimeException("Project has no Makefile");
38+
}
39+
40+
File workDir = projectInfo.getProjectDirAsFile();
41+
String[] command = {"make", "test"};
42+
43+
final ProcessRunner runner = new ProcessRunner(command, workDir, io);
44+
4645
try {
4746
ProcessResult result = runner.call();
4847
int ret = result.statusCode;
4948
if (ret != 0) {
5049
io.select();
50+
log.log(Level.INFO, "Compile resulted in non-zero exit code {0}", result.statusCode);
51+
return new TestRunResult(false);
5152
}
52-
return ret;
53+
54+
log.info("Running tests");
55+
return runTests(projectInfo, true);
5356
} catch (Exception ex) {
54-
log.log(INFO, "Compilation failed, {0}", ex.getMessage());
5557
io.select();
5658
throw ex;
5759
}
5860
}
5961
};
6062
}
6163

62-
@Override
63-
public Callable<TestRunResult> getTestRunningTask(final TmcProjectInfo projectInfo) {
64-
return new Callable<TestRunResult>() {
65-
@Override
66-
public TestRunResult call() throws Exception {
67-
return runTests(projectInfo, true);
68-
}
69-
};
70-
}
71-
7264
// TODO: use make
7365
private TestRunResult runTests(final TmcProjectInfo projectInfo, final boolean withValgrind) throws Exception {
74-
log.log(INFO, "Running tests {0}", projectInfo.getProjectName());
66+
log.log(Level.INFO, "Running tests {0}", projectInfo.getProjectName());
7567
final File testDir = projectInfo.getProjectDirAsFile();
7668
String[] command;
7769

@@ -83,7 +75,7 @@ private TestRunResult runTests(final TmcProjectInfo projectInfo, final boolean w
8375
command = new String[]{testDir.getAbsolutePath()
8476
+ File.separatorChar + "test" + File.separatorChar + "test"};
8577
}
86-
log.log(INFO, "Running tests for project {0} with command {1}",
78+
log.log(Level.INFO, "Running tests for project {0} with command {1}",
8779
new Object[]{projectInfo.getProjectName(), Arrays.deepToString(command)});
8880

8981
ProcessRunner runner = new ProcessRunner(command, testDir, IOProvider.getDefault()
@@ -94,11 +86,11 @@ private TestRunResult runTests(final TmcProjectInfo projectInfo, final boolean w
9486
runner.call();
9587
log.info("Running tests completed");
9688
} catch (IOException e) {
97-
log.log(INFO, "IOException while running tests, kinda wanted. {0}", e.getMessage());
89+
log.log(Level.INFO, "IOException while running tests, kinda wanted. {0}", e.getMessage());
9890
if (withValgrind) {
9991
return runTests(projectInfo, false);
10092
} else {
101-
log.log(WARNING, "Failed to run tests for project: \"{0}\" with command: \"{1}\".\n\"{2}\"",
93+
log.log(Level.WARNING, "Failed to run tests for project: \"{0}\" with command: \"{1}\".\n\"{2}\"",
10294
new Object[]{projectInfo.getProjectName(), Arrays.deepToString(command), e.getMessage()});
10395
throw new UserVisibleException("Failed to run tests:\n" + e.getMessage());
10496
}
@@ -111,10 +103,10 @@ private TestRunResult runTests(final TmcProjectInfo projectInfo, final boolean w
111103
Exercise exercise = projectMediator.tryGetExerciseForProject(projectInfo, courseDb);
112104

113105
if (exercise != null) {
114-
log.log(INFO, "Parsing exercises with valgrind strategy {0}", exercise.getValgrindStrategy());
106+
log.log(Level.INFO, "Parsing exercises with valgrind strategy {0}", exercise.getValgrindStrategy());
115107
return resultParser.parseCTestResults(resultsFile, valgrindLog, exercise.getValgrindStrategy());
116108
} else {
117-
log.log(INFO, "Parsing exercises with out valgrind strategy");
109+
log.log(Level.INFO, "Parsing exercises with out valgrind strategy");
118110
return resultParser.parseCTestResults(resultsFile, valgrindLog, null);
119111
}
120112
}

tmc-plugin/src/fi/helsinki/cs/tmc/runners/MavenExerciseRunner.java

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,51 +14,56 @@
1414
import java.util.Map;
1515
import java.util.concurrent.Callable;
1616
import java.util.logging.Level;
17+
import java.util.logging.Logger;
1718
import org.apache.commons.lang3.StringUtils;
1819
import org.openide.windows.IOProvider;
1920
import org.openide.windows.InputOutput;
2021

2122
public class MavenExerciseRunner extends AbstractJavaExerciseRunner {
23+
2224
private static final String MAVEN_TEST_RUN_GOAL = "fi.helsinki.cs.tmc:tmc-maven-plugin:1.6:test";
25+
private static final Logger log = Logger.getLogger(MavenExerciseRunner.class.getName());
2326

2427
@Override
25-
public Callable<Integer> getCompilingTask(TmcProjectInfo projectInfo) {
26-
File projectDir = projectInfo.getProjectDirAsFile();
27-
28-
String goal = "test-compile";
28+
public Callable<TestRunResult> getTestRunningTask(final TmcProjectInfo projectInfo) {
2929
final InputOutput inOut = IOProvider.getDefault().getIO(projectInfo.getProjectName(), false);
3030

31-
final ProcessRunner runner = new MavenRunBuilder()
32-
.setProjectDir(projectDir)
33-
.addGoal(goal)
34-
.setIO(inOut)
35-
.createProcessRunner();
36-
37-
return new Callable<Integer>() {
31+
return new Callable<TestRunResult>() {
3832
@Override
39-
public Integer call() throws Exception {
33+
public TestRunResult call() throws Exception {
34+
File projectDir = projectInfo.getProjectDirAsFile();
35+
log.info("Starting compile");
36+
String goal = "test-compile";
37+
38+
final ProcessRunner runner = new MavenRunBuilder()
39+
.setProjectDir(projectDir)
40+
.addGoal(goal)
41+
.setIO(inOut)
42+
.createProcessRunner();
4043
try {
4144
ProcessResult result = runner.call();
4245
int ret = result.statusCode;
4346
if (ret != 0) {
4447
inOut.select();
48+
log.log(Level.INFO, "Compile resulted in non-zero exit code {0}", result.statusCode);
49+
return new TestRunResult(false);
50+
} else {
51+
log.log(Level.INFO, "Running tests");
52+
return runTests(projectInfo, inOut);
4553
}
46-
return ret;
4754
} catch (Exception ex) {
4855
inOut.select();
4956
throw ex;
5057
}
5158
}
59+
5260
};
5361
}
5462

55-
@Override
56-
public Callable<TestRunResult> getTestRunningTask(final TmcProjectInfo projectInfo) {
63+
public TestRunResult runTests(final TmcProjectInfo projectInfo, InputOutput inOut) throws Exception {
5764
final File projectDir = projectInfo.getProjectDirAsFile();
5865
String goal = MAVEN_TEST_RUN_GOAL;
5966
Map<String, String> props = new HashMap<String, String>();
60-
InputOutput inOut = getIoTab();
61-
6267
List<String> jvmOpts = new ArrayList<String>();
6368

6469
Exercise exercise = tryGetExercise(projectInfo.getProject());
@@ -82,16 +87,11 @@ public Callable<TestRunResult> getTestRunningTask(final TmcProjectInfo projectIn
8287
.setIO(inOut)
8388
.createProcessRunner();
8489

85-
return new Callable<TestRunResult>() {
86-
@Override
87-
public TestRunResult call() throws Exception {
88-
runner.call();
89-
File resultsFile = new File(
90-
projectDir.getPath() + File.separator
91-
+ "target" + File.separator
92-
+ "test_output.txt");
93-
return resultParser.parseTestResults(resultsFile);
94-
}
95-
};
90+
runner.call();
91+
File resultsFile = new File(
92+
projectDir.getPath() + File.separator
93+
+ "target" + File.separator
94+
+ "test_output.txt");
95+
return resultParser.parseTestResults(resultsFile);
9696
}
9797
}

0 commit comments

Comments
 (0)