diff --git a/.old_travis.yml b/.old_travis.yml
new file mode 100644
index 000000000..a551fc679
--- /dev/null
+++ b/.old_travis.yml
@@ -0,0 +1,45 @@
+language: java
+sudo: false
+cache:
+ directories:
+ - "$HOME/.m2"
+addons:
+ apt:
+ sources:
+ - deadsnakes
+ packages:
+ - valgrind
+ - check
+ - python3.4
+env:
+ global:
+ - secure: yiW+hXiZEycKFzF19rLlejJX8BTGbncSisBHyE8uulZee5n7UVGXnG1yvt9+6hz0nvMbxL7r1Daql0xxRHXUFB9VYVUKhF0ycHyJO5ze87U51mlIKAL8UnCkmxpkHNdxY45olEdK+mEbZBtot67nenlwGDfxLI7laITkR8IBAvY=
+ - secure: WVOHmRlzHZhuYqpTVFR2ZjdVDugr/EGEZGhnkWFFh6DE2zfa+na8WSLQdynHjTH1sL2DMg+p4l8siLoKk6Kn9wh+Wah2GP54oKQNIvt+Zl0olTR8TZq/uEo1iU4dqsDbMscId2xK7imdQ9wMKXV0t/bqhjiFR/wxheR96WxvIVs=
+ - M3_HOME=/usr/local/maven
+
+before_install:
+ - curl -L https://static.rust-lang.org/rustup.sh | sh -s -- --channel=stable --yes --prefix=$PWD --disable-sudo
+ - export PATH=$PATH:$PWD/bin
+ - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/lib
+ - mkdir $HOME/bin && ln -s $(which python3.4) $HOME/bin/python3 && export PATH="$HOME/bin:$PATH"
+ - mvn install -Dmaven.test.skip=true
+script:
+ - mvn clean test
+ - mvn checkstyle:check
+ - . ./clitest.sh
+after_success:
+ - mvn clean cobertura:cobertura org.eluder.coveralls:coveralls-maven-plugin:report
+ - ./deploy.sh
+os:
+ - linux
+ - osx
+jdk:
+ - oraclejdk8
+ - oraclejdk7
+ - openjdk7
+matrix:
+ allow_failures:
+ - os: osx
+notifications:
+ slack:
+ secure: elwVbriXdc/RkeP3UfVpSC0N6mbdk60ro7Pu1+2ddktmgQIEHjAVSdzpy2FLGTz/gK2MEXo2XU1rSg3t8GqlJNh1RTASzhyhcCUJTa7UdKe84mcRWDxJffunQKsBpUJv71tXBy1OyL8pcdnw1qkpr5NDyqXvBk67VwepVqy8em4=
diff --git a/.travis.yml b/.travis.yml
index ff8e0e38d..7da3a6b76 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,7 +10,6 @@ addons:
packages:
- valgrind
- check
- - python3.4
env:
global:
- secure: yiW+hXiZEycKFzF19rLlejJX8BTGbncSisBHyE8uulZee5n7UVGXnG1yvt9+6hz0nvMbxL7r1Daql0xxRHXUFB9VYVUKhF0ycHyJO5ze87U51mlIKAL8UnCkmxpkHNdxY45olEdK+mEbZBtot67nenlwGDfxLI7laITkR8IBAvY=
@@ -18,13 +17,13 @@ env:
- M3_HOME=/usr/local/maven
before_install:
- - curl -L https://static.rust-lang.org/rustup.sh | sh -s -- --channel=stable --yes --prefix=$PWD --disable-sudo
- export PATH=$PATH:$PWD/bin
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/lib
- mkdir -p $HOME/bin && ln -s $(which python3.4) $HOME/bin/python3 && export PATH="$HOME/bin:$PATH"
+ - export PATH="$HOME/bin:$PATH"
- mvn install -Dmaven.test.skip=true
script:
- - mvn clean test
+ - mvn clean test -pl tmc-langs-r
- mvn checkstyle:check
- . ./clitest.sh
after_success:
@@ -40,6 +39,4 @@ jdk:
matrix:
allow_failures:
- os: osx
-notifications:
- slack:
- secure: elwVbriXdc/RkeP3UfVpSC0N6mbdk60ro7Pu1+2ddktmgQIEHjAVSdzpy2FLGTz/gK2MEXo2XU1rSg3t8GqlJNh1RTASzhyhcCUJTa7UdKe84mcRWDxJffunQKsBpUJv71tXBy1OyL8pcdnw1qkpr5NDyqXvBk67VwepVqy8em4=
+ - jdk: oraclejdk7
diff --git a/clitest.sh b/clitest.sh
index eba28c5b8..cb422216e 100755
--- a/clitest.sh
+++ b/clitest.sh
@@ -2,7 +2,7 @@
# The intention is not to really validate the results of the command,
# but to make note should any commands fail and other packaging failures.
-mvn clean package -Dmaven.test.skip=true
+mvn clean package -Dmaven.test.skip=true
java -jar tmc-langs-cli/target/tmc-langs-cli-*-SNAPSHOT.jar scan-exercise --exercisePath tmc-langs-java/src/test/resources/maven_exercise --outputPath a
cat a
diff --git a/old_clitest.sh b/old_clitest.sh
new file mode 100755
index 000000000..eba28c5b8
--- /dev/null
+++ b/old_clitest.sh
@@ -0,0 +1,12 @@
+#!/bin/bash -v
+# The intention is not to really validate the results of the command,
+# but to make note should any commands fail and other packaging failures.
+
+mvn clean package -Dmaven.test.skip=true
+
+java -jar tmc-langs-cli/target/tmc-langs-cli-*-SNAPSHOT.jar scan-exercise --exercisePath tmc-langs-java/src/test/resources/maven_exercise --outputPath a
+cat a
+
+java -jar tmc-langs-cli/target/tmc-langs-cli-*-SNAPSHOT.jar prepare-stubs --exercisePath tmc-langs-java/src/test/resources/ant_arith_funcs/ --outputPath arithfuncs-proj
+java -jar tmc-langs-cli/target/tmc-langs-cli-*-SNAPSHOT.jar checkstyle --exercisePath tmc-langs-cli/src/test/resources/arith_funcs --locale=en --outputPath tmp
+cat tmp
diff --git a/tmc-langs-r/pom.xml b/tmc-langs-r/pom.xml
index 2727e5e9a..d84d23f82 100644
--- a/tmc-langs-r/pom.xml
+++ b/tmc-langs-r/pom.xml
@@ -7,6 +7,20 @@
0.7.7-SNAPSHOT
tmc-langs-r
- 1.0-SNAPSHOT
+ 0.7.7-SNAPSHOT
jar
+
+
+
+ fi.helsinki.cs.tmc
+ tmc-langs-framework
+ 0.7.7-SNAPSHOT
+
+
+ fi.helsinki.cs.tmc
+ tmc-langs-util
+ 0.7.7-SNAPSHOT
+
+
+
\ No newline at end of file
diff --git a/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RPlugin.java b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RPlugin.java
new file mode 100644
index 000000000..fc2bfb89f
--- /dev/null
+++ b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RPlugin.java
@@ -0,0 +1,106 @@
+package fi.helsinki.cs.tmc.langs.r;
+
+import fi.helsinki.cs.tmc.langs.AbstractLanguagePlugin;
+import fi.helsinki.cs.tmc.langs.abstraction.ValidationResult;
+import fi.helsinki.cs.tmc.langs.domain.ExerciseBuilder;
+import fi.helsinki.cs.tmc.langs.domain.ExerciseDesc;
+import fi.helsinki.cs.tmc.langs.domain.RunResult;
+import fi.helsinki.cs.tmc.langs.io.StudentFilePolicy;
+import fi.helsinki.cs.tmc.langs.io.sandbox.StudentFileAwareSubmissionProcessor;
+import fi.helsinki.cs.tmc.langs.io.sandbox.SubmissionProcessor;
+import fi.helsinki.cs.tmc.langs.io.zip.StudentFileAwareUnzipper;
+import fi.helsinki.cs.tmc.langs.io.zip.StudentFileAwareZipper;
+import fi.helsinki.cs.tmc.langs.io.zip.Unzipper;
+import fi.helsinki.cs.tmc.langs.io.zip.Zipper;
+import fi.helsinki.cs.tmc.langs.python3.Python3TestResultParser;
+import fi.helsinki.cs.tmc.langs.utils.ProcessRunner;
+
+import com.google.common.base.Optional;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.SystemUtils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Locale;
+
+public final class RPlugin extends AbstractLanguagePlugin {
+
+ private static final String CANNOT_RUN_TESTS_MESSAGE = "Failed to run tests.";
+ private static final String CANNOT_PARSE_TEST_RESULTS_MESSAGE = "Failed to read test results.";
+ private static final String CANNOT_SCAN_EXERCISE_MESSAGE = "Failed to scan exercise.";
+ private static final String CANNOT_PARSE_EXERCISE_DESCRIPTION_MESSAGE =
+ "Failed to parse exercise description.";
+
+ private static Logger log = LoggerFactory.getLogger(RPlugin.class);
+
+ public RPlugin() {
+ super(
+ new ExerciseBuilder(),
+ new StudentFileAwareSubmissionProcessor(),
+ new StudentFileAwareZipper(),
+ new StudentFileAwareUnzipper());
+ }
+
+ @Override
+ public boolean isExerciseTypeCorrect(Path path) {
+ return false;
+ }
+
+ @Override
+ protected StudentFilePolicy getStudentFilePolicy(Path projectPath) {
+ return null;
+ }
+
+ @Override
+ public String getPluginName() {
+ return null;
+ }
+
+ @Override
+ public Optional scanExercise(Path path, String exerciseName) {
+ return null;
+ }
+
+ @Override
+ public RunResult runTests(Path path) {
+
+ ProcessRunner runner = new ProcessRunner(getTestCommand(), path);
+ try {
+ runner.call();
+ } catch (Exception e) {
+ log.error(CANNOT_RUN_TESTS_MESSAGE, e);
+ }
+
+ try {
+ return new RTestResultParser(path).parse();
+ } catch (IOException e) {
+ log.error(CANNOT_PARSE_TEST_RESULTS_MESSAGE, e);
+ }
+ return null;
+ }
+
+ @Override
+ public ValidationResult checkCodeStyle(Path path, Locale messageLocale) {
+ return null;
+ }
+
+ private String[] getTestCommand() {
+ String[] rscr = new String[] {"Rscript", "-e"};
+ String[] command;
+ if (SystemUtils.IS_OS_WINDOWS) {
+ command = new String[] {"\"library('tmcRtestrunner');runTestsWithDefault(TRUE)\""};
+ } else {
+ command = new String[] {"\"library(tmcRtestrunner);runTests(\"$PWD\", print=TRUE)\""};
+ }
+ return ArrayUtils.addAll(rscr, command);
+ }
+
+ @Override
+ public void clean(Path path) {
+
+ }
+}
diff --git a/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RTestResultParser.java b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RTestResultParser.java
index d9e76cd72..0ab926fa3 100644
--- a/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RTestResultParser.java
+++ b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RTestResultParser.java
@@ -1,8 +1,79 @@
package fi.helsinki.cs.tmc.langs.r;
+import fi.helsinki.cs.tmc.langs.domain.RunResult;
+import fi.helsinki.cs.tmc.langs.domain.TestResult;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
public class RTestResultParser {
- public RTestResultParser() {
+ Path path;
+ private ObjectMapper mapper;
+
+ private static Path RESULT_FILE = Paths.get(".results.json");
+
+ public RTestResultParser(Path path) {
+ this.path = path;
+ this.mapper = new ObjectMapper();
+ }
+
+ RunResult parse() throws IOException {
+ List testResults = getTestResults();
+
+ RunResult.Status status = RunResult.Status.PASSED;
+ for (TestResult result : testResults) {
+ if (!result.isSuccessful()) {
+ status = RunResult.Status.TESTS_FAILED;
+ }
+ }
+
+ ImmutableList immutableResults = ImmutableList.copyOf(testResults);
+ ImmutableMap logs = ImmutableMap.copyOf(new HashMap());
+ return new RunResult(status, immutableResults, logs);
+ }
+
+ private List getTestResults() throws IOException {
+ byte[] json = Files.readAllBytes(path.resolve(RESULT_FILE));
+
+ List results = new ArrayList<>();
+
+ JsonNode tree = mapper.readTree(json);
+ for (JsonNode node : tree) {
+ results.add(toTestResult(node));
+ }
+
+ return results;
}
+ private TestResult toTestResult(JsonNode node) {
+ List points = new ArrayList<>();
+ for (JsonNode point : node.get("points")) {
+ points.add(point.asText());
+ }
+
+ List backTrace = new ArrayList<>();
+ for (JsonNode line : node.get("backtrace")) {
+ backTrace.add(line.asText());
+ }
+
+ boolean passed = node.get("status").asText().equals("pass");
+
+ return new TestResult(
+ node.get("name").asText(),
+ passed,
+ ImmutableList.copyOf(points),
+ node.get("message").toString(),
+ ImmutableList.copyOf(backTrace));
+ }
}
diff --git a/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/TestMain.java b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/TestMain.java
new file mode 100644
index 000000000..249a726c0
--- /dev/null
+++ b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/TestMain.java
@@ -0,0 +1,76 @@
+package fi.helsinki.cs.tmc.langs.r;
+
+import fi.helsinki.cs.tmc.langs.domain.RunResult;
+import fi.helsinki.cs.tmc.langs.domain.TestResult;
+import fi.helsinki.cs.tmc.langs.utils.ProcessRunner;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.SystemUtils;
+
+import java.io.IOException;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class TestMain {
+
+ /**
+ * Just testing.
+ *
+ * @param args Nothing.
+ */
+ public static void main(String[] args) {
+
+ //For now, add the path you want to test here fully,
+ //for example: pathToGithubFolder/tmc-r/example_projects/example_project1
+ String exampleProjectLocation = "/tmc-r/example_projects/example_project1";
+ Path path = Paths.get(exampleProjectLocation);
+ RunResult runRes = runTests(path);
+ printTestResult(runRes);
+ RunResult rr;
+
+/* try {
+ rr = new RTestResultParser(path).parse();
+ for (TestResult tr : rr.testResults) {
+ System.out.println(tr.toString());
+ }
+ } catch (IOException e) {
+ System.out.println("Something wrong: " + e.getMessage());
+ }*/
+ }
+
+ public static void printTestResult(RunResult rr) {
+ for (TestResult tr : rr.testResults) {
+ System.out.println(tr.toString());
+ }
+ }
+
+
+ public static RunResult runTests(Path path) {
+
+ ProcessRunner runner = new ProcessRunner(getTestCommand(), path);
+ try {
+ runner.call();
+ } catch (Exception e) {
+ System.out.println("Something wrong: " + e.getMessage());
+ }
+
+ try {
+ return new RTestResultParser(path).parse();
+ } catch (IOException e) {
+ System.out.println("Something wrong: " + e.getMessage());
+ }
+ return null;
+ }
+
+ private static String[] getTestCommand() {
+ String[] rscr = new String[]{"Rscript", "-e"};
+ String[] command;
+ if (SystemUtils.IS_OS_WINDOWS) {
+ command = new String[] {"\"library('tmcRtestrunner');runTestsWithDefault(TRUE)\""};
+ } else {
+ command = new String[] {"\"library(tmcRtestrunner);runTests(\"$PWD\", print=TRUE)\""};
+ }
+ return ArrayUtils.addAll(rscr, command);
+ }
+}
diff --git a/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RTestResultParserTest.java b/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RTestResultParserTest.java
new file mode 100644
index 000000000..f59fd828e
--- /dev/null
+++ b/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RTestResultParserTest.java
@@ -0,0 +1,46 @@
+package fi.helsinki.cs.tmc.langs.r;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import fi.helsinki.cs.tmc.langs.domain.RunResult;
+import fi.helsinki.cs.tmc.langs.domain.TestResult;
+import fi.helsinki.cs.tmc.langs.utils.TestUtils;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+public class RTestResultParserTest {
+
+ private RunResult rr;
+ private Path jsonDir;
+
+ public RTestResultParserTest() {
+ jsonDir = TestUtils.getPath(getClass(), "example_json");
+ try {
+ rr = new RTestResultParser(jsonDir).parse();
+ } catch (IOException e) {
+ System.out.println("Something wrong: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void testThatParseSeemsToWorkOnExampleJson() {
+ assertEquals(RunResult.Status.TESTS_FAILED, rr.status);
+ assertEquals(22, rr.testResults.size());
+
+ for (TestResult tr : rr.testResults) {
+ if (tr.getName().equals("Addition works")) {
+ assertTrue(tr.isSuccessful());
+ assertEquals(2, tr.points.size());
+ assertTrue(tr.points.contains("r1.1"));
+ assertTrue(tr.points.contains("r1.2"));
+ }
+ if (!tr.isSuccessful()) {
+ assertEquals("Dummy test set to fail", tr.getName());
+ }
+ }
+ }
+}
diff --git a/tmc-langs-r/src/test/resources/example_json/.results.json b/tmc-langs-r/src/test/resources/example_json/.results.json
new file mode 100644
index 000000000..5d0cb9f6d
--- /dev/null
+++ b/tmc-langs-r/src/test/resources/example_json/.results.json
@@ -0,0 +1,204 @@
+[
+ {
+ "status": "passed",
+ "name": "Addition works",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r1.1",
+ "r1.2"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Multiplication works",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r1.3",
+ "r1.4"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Subtraction works",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r1.5"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Division works",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r1.6"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Test with no points",
+ "message": "",
+ "backtrace": "",
+ "points": [
+
+ ]
+ },
+ {
+ "status": "failed",
+ "name": "Dummy test set to fail",
+ "message": "Failed with call: expect_true, FALSE\nFALSE isn't true.\nFailed with call: expect_equal, 1, 2\n1 not equal to 2.\n1/1 mismatches\n[1] 1 - 2 == -1\n",
+ "backtrace": "",
+ "points": [
+
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Matrix transpose with [[1,2]] works",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r2.1"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Matrix transpose with [[1,2],[3,4]] works",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r2.2"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Constant string works",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r3.1"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 1 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.1"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 2 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.2"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 3 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.3",
+ "r4.4"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 4 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.5"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 5 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.6"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 6 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.7"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 7 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.8"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 8 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.9"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 9 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.10"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 10 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.11"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 11 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.12"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 12 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.13"
+ ]
+ },
+ {
+ "status": "passed",
+ "name": "Exercise 13 is correct",
+ "message": "",
+ "backtrace": "",
+ "points": [
+ "r4.14"
+ ]
+ }
+]
+