From 99165037da1193ce19ece67b3571c5ea40812416 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Fri, 4 Sep 2015 00:43:07 +0300 Subject: [PATCH 01/13] Added preliminary plugin and student file policy for Cargo and rust. And some tests for them. --- .../cs/tmc/langs/rust/CargoPlugin.java | 144 ++++++++++++++++++ .../cs/tmc/langs/rust/CargoResultParser.java | 108 +++++++++++++ .../langs/rust/CargoStudentFilePolicy.java | 26 ++++ .../cs/tmc/langs/rust/util/Constants.java | 10 ++ .../cs/tmc/langs/rust/CargoPluginTest.java | 51 +++++++ .../src/test/resources/passing/Cargo.lock | 4 + .../src/test/resources/passing/Cargo.toml | 4 + .../src/test/resources/passing/src/lib.rs | 5 + .../src/test/resources/passing/tests/mod.rs | 7 + 9 files changed, 359 insertions(+) create mode 100644 tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java create mode 100644 tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java create mode 100644 tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java create mode 100644 tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/util/Constants.java create mode 100644 tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java create mode 100644 tmc-langs-rust/src/test/resources/passing/Cargo.lock create mode 100644 tmc-langs-rust/src/test/resources/passing/Cargo.toml create mode 100644 tmc-langs-rust/src/test/resources/passing/src/lib.rs create mode 100644 tmc-langs-rust/src/test/resources/passing/tests/mod.rs diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java new file mode 100644 index 000000000..a5e94a575 --- /dev/null +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java @@ -0,0 +1,144 @@ +package fi.helsinki.cs.tmc.langs.rust; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import fi.helsinki.cs.tmc.langs.AbstractLanguagePlugin; +import fi.helsinki.cs.tmc.langs.abstraction.ValidationResult; +import fi.helsinki.cs.tmc.langs.domain.Configuration; +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.domain.RunResult.Status; +import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; +import fi.helsinki.cs.tmc.langs.domain.TestResult; +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.rust.util.Constants; +import fi.helsinki.cs.tmc.langs.utils.ProcessResult; +import fi.helsinki.cs.tmc.langs.utils.ProcessRunner; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javafx.concurrent.Worker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CargoPlugin extends AbstractLanguagePlugin { + + private static final Logger log = LoggerFactory.getLogger(CargoPlugin.class); + private static final RunResult EMPTY_FAILURE = new RunResult( + Status.COMPILE_FAILED, + ImmutableList.of(), + new ImmutableMap.Builder().build()); + + public CargoPlugin() { + super( + new ExerciseBuilder(), + new StudentFileAwareSubmissionProcessor(), + new StudentFileAwareZipper(), + new StudentFileAwareUnzipper()); + } + + @Override + public boolean isExerciseTypeCorrect(Path path) { + return Files.isRegularFile(path.resolve(Constants.CARGO_TOML)); + } + + @Override + protected StudentFilePolicy getStudentFilePolicy(Path projectPath) { + return new CargoStudentFilePolicy(projectPath); + } + + @Override + public ValidationResult checkCodeStyle(Path path) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getLanguageName() { + return "cargo"; + } + + @Override + public Optional scanExercise(Path path, String exerciseName) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public RunResult runTests(Path path) { + Optional result = build(path); + if (result.isPresent()) { + log.info("Failed to compile project."); + return result.get(); + } + return runBuiltTests(path); + } + + private Optional build(Path dir) { + String[] command = {"cargo", "test", "--no-run"}; + log.info("Building project with command {0}", Arrays.deepToString(command)); + Optional result = run(command, dir); + if (result.isPresent()) { + if (result.get().statusCode == 0) { + return Optional.absent(); + } + return Optional.of(filledFailure(result.get())); + } + return Optional.of(EMPTY_FAILURE); + } + + private RunResult runBuiltTests(Path dir) { + String[] command = {"cargo", "test"}; + log.info("Running tests with command {0}", Arrays.deepToString(command)); + Optional result = run(command, dir); + if (result.isPresent()) { + if (result.get().statusCode == 0) { + return parseResult(result.get(), dir); + } + return filledFailure(result.get()); + } + return EMPTY_FAILURE; + } + + private Optional run(String[] command, Path dir) { + ProcessRunner runner = new ProcessRunner(command, dir); + try { + return Optional.of(runner.call()); + } catch (Exception e) { + return Optional.absent(); + } + } + + private RunResult filledFailure(ProcessResult processResult) { + byte[] output = processResult.output.getBytes(StandardCharsets.UTF_8); + byte[] errorOutput = processResult.errorOutput.getBytes(StandardCharsets.UTF_8); + ImmutableMap.Builder logs = new ImmutableMap.Builder<>(); + logs.put(SpecialLogs.STDOUT, output); + logs.put(SpecialLogs.STDERR, errorOutput); + return new RunResult( + Status.COMPILE_FAILED, + ImmutableList.of(), + logs.build()); + } + + private RunResult parseResult(ProcessResult processResult, Path path) { + Configuration configuration = new Configuration(path); + return new CargoResultParser().parse(processResult); + } + +} diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java new file mode 100644 index 000000000..2a120d1f5 --- /dev/null +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -0,0 +1,108 @@ +package fi.helsinki.cs.tmc.langs.rust; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import fi.helsinki.cs.tmc.langs.domain.RunResult; +import fi.helsinki.cs.tmc.langs.domain.RunResult.Status; +import fi.helsinki.cs.tmc.langs.domain.TestResult; +import fi.helsinki.cs.tmc.langs.utils.ProcessResult; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CargoResultParser { + + private static final RunResult PARSING_FAILED = new RunResult( + Status.GENERIC_ERROR, + ImmutableList.of(), + new ImmutableMap.Builder() + .put("generic_error_message", "Test results couldn't be parsed." + .getBytes(StandardCharsets.UTF_8)) + .build()); + + //test result: FAILED. 25 passed; 1 failed; 0 ignored; 0 measured + private static final Pattern RESULT = Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); + + public RunResult parse(ProcessResult processResult) { + String[] lines = processResult.output.split(System.lineSeparator()); + String last = lines[lines.length - 1]; + Matcher matcher = RESULT.matcher(last); + if (matcher.matches()) { + int fails = Integer.parseInt(matcher.group("fails")); + int passes = Integer.parseInt(matcher.group("passes")); + int total = fails + passes; + Optional> failures + = findFailures(processResult.errorOutput, fails); + if (failures.isPresent()) { + Status status = fails == 0 ? Status.PASSED : Status.TESTS_FAILED; + Optional> tests = parseResults(lines, total); + if (tests.isPresent()) { + return new RunResult( + status, + buildTestResults(tests.get(), failures.get()), + ImmutableMap.of()); + } + } + } + return PARSING_FAILED; + } + + //test test::dim4::test_4d_1_80_perioditic ... ok + private static final Pattern TEST = Pattern.compile("test (?.*) \\.\\.\\. .*"); + + private Optional> parseResults(String[] lines, int tests) { + List result = new ArrayList<>(); + for (int n = 3; n < 3 + tests; n++) { + Matcher matcher = TEST.matcher(lines[n]); + if (matcher.matches()) { + result.add(matcher.group("name")); + } else { + return Optional.absent(); + } + } + return Optional.of(result); + } + + //thread 'test::dim2::test_2d_1_80_normal' panicked at 'assertion failed: false', src\test\dim2.rs:12 + private static final Pattern FAILURES = Pattern.compile("thread '(?.*)' panicked at '(?.*)', .*"); + + private Optional> findFailures(String errorOutput, int fails) { + Map result = new HashMap<>(); + String[] lines = errorOutput.split(System.lineSeparator()); + for (int n = lines.length - 1; n > lines.length - fails - 1; n--) { + Matcher matcher = FAILURES.matcher(lines[n]); + if (matcher.matches()) { + result.put(matcher.group("name"), matcher.group("description")); + } else { + return Optional.absent(); + } + } + return Optional.of(result); + } + + private ImmutableList buildTestResults(List results, Map failures) { + ImmutableList.Builder testResults = ImmutableList.builder(); + for (String test : results) { + String description = failures.get(test); + boolean fail = true; + if (description == null) { + description = ""; + fail = false; + } + TestResult testResult = new TestResult( + test, + fail, + ImmutableList.of(), + description, + ImmutableList.of()); + testResults.add(testResult); + } + return testResults.build(); + } +} diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java new file mode 100644 index 000000000..a9e64fc24 --- /dev/null +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java @@ -0,0 +1,26 @@ +package fi.helsinki.cs.tmc.langs.rust; + +import fi.helsinki.cs.tmc.langs.io.ConfigurableStudentFilePolicy; +import fi.helsinki.cs.tmc.langs.rust.util.Constants; +import java.nio.file.Path; + +public class CargoStudentFilePolicy extends ConfigurableStudentFilePolicy { + + public CargoStudentFilePolicy(Path configFileParent) { + super(configFileParent); + } + + /** + * Returns {@code true} for all files in the projectRoot/src directory and other + * files required for building the project. + * + *

Will NOT return {@code true} for any test files. If test file modification are part + * of the exercise, those test files are whitelisted as ExtraStudentFiles and the + * decision to move them is made by {@link ConfigurableStudentFilePolicy}. + */ + @Override + public boolean isStudentSourceFile(Path path) { + return !path.endsWith(Constants.CARGO_TOML) && path.startsWith(Constants.SOURCE); + } + +} diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/util/Constants.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/util/Constants.java new file mode 100644 index 000000000..e89f06cfd --- /dev/null +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/util/Constants.java @@ -0,0 +1,10 @@ + +package fi.helsinki.cs.tmc.langs.rust.util; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Constants { + public static final Path CARGO_TOML = Paths.get("Cargo.toml"); + public static final Path SOURCE = Paths.get("src"); +} diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java new file mode 100644 index 000000000..1413fc710 --- /dev/null +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java @@ -0,0 +1,51 @@ +package fi.helsinki.cs.tmc.langs.rust; + +import com.google.common.base.Optional; +import fi.helsinki.cs.tmc.langs.abstraction.ValidationResult; +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.utils.TestUtils; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +public class CargoPluginTest { + + private CargoPlugin cargoPlugin; + + public CargoPluginTest() { + } + + @Before + public void setUp() { + cargoPlugin = new CargoPlugin(); + } + + @Test + public void isExerciseCorrectTypeDoesntBreakByDirectoryNamedCargoToml() throws IOException { + Path parent = Files.createTempDirectory("tmc-cargo-test"); + Path cargoToml = parent.resolve("Cargo.toml"); + Files.createDirectory(cargoToml); + + assertFalse(cargoPlugin.isExerciseTypeCorrect(parent)); + + Files.delete(cargoToml); + Files.delete(parent); + } + + @Test + public void testMakeProjectWithPassingTestsCompilesAndPassesTests() { + Path path = TestUtils.getPath(getClass(), "passing"); + RunResult result = cargoPlugin.runTests(path); + + assertEquals(RunResult.Status.PASSED, result.status); + } + +} diff --git a/tmc-langs-rust/src/test/resources/passing/Cargo.lock b/tmc-langs-rust/src/test/resources/passing/Cargo.lock new file mode 100644 index 000000000..e887b01b3 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/passing/Cargo.lock @@ -0,0 +1,4 @@ +[root] +name = "passing_suite" +version = "0.1.0" + diff --git a/tmc-langs-rust/src/test/resources/passing/Cargo.toml b/tmc-langs-rust/src/test/resources/passing/Cargo.toml new file mode 100644 index 000000000..bf8600aa7 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/passing/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "passing_suite" +version = "0.1.0" +authors = [""] diff --git a/tmc-langs-rust/src/test/resources/passing/src/lib.rs b/tmc-langs-rust/src/test/resources/passing/src/lib.rs new file mode 100644 index 000000000..c7770c937 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/passing/src/lib.rs @@ -0,0 +1,5 @@ + +pub fn mul_xor_add(a: u64, b: u64) -> u64 { + let x = a * b; + (x ^ a) + (x ^ b) +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/passing/tests/mod.rs b/tmc-langs-rust/src/test/resources/passing/tests/mod.rs new file mode 100644 index 000000000..8f8088a28 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/passing/tests/mod.rs @@ -0,0 +1,7 @@ +extern crate passing_suite; +use passing_suite::mul_xor_add; + +#[test] +fn it_shall_work() { + assert_eq!(9, mul_xor_add(2, 3)); +} \ No newline at end of file From e2af3269c5ca0bf20d85669c56a370581976dceb Mon Sep 17 00:00:00 2001 From: Wadelma Date: Fri, 4 Sep 2015 01:48:13 +0300 Subject: [PATCH 02/13] Fixed typo and line splitting. Changed test project. --- .../fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java | 4 ++-- tmc-langs-rust/src/test/resources/passing/Cargo.lock | 4 ---- tmc-langs-rust/src/test/resources/passing/Cargo.toml | 4 ++-- tmc-langs-rust/src/test/resources/passing/tests/mod.rs | 5 ++--- 4 files changed, 6 insertions(+), 11 deletions(-) delete mode 100644 tmc-langs-rust/src/test/resources/passing/Cargo.lock diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java index 2a120d1f5..e7c3d5de4 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -27,10 +27,10 @@ public class CargoResultParser { .build()); //test result: FAILED. 25 passed; 1 failed; 0 ignored; 0 measured - private static final Pattern RESULT = Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); + private static final Pattern RESULT = Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); public RunResult parse(ProcessResult processResult) { - String[] lines = processResult.output.split(System.lineSeparator()); + String[] lines = processResult.output.split("\\r?\\n"); String last = lines[lines.length - 1]; Matcher matcher = RESULT.matcher(last); if (matcher.matches()) { diff --git a/tmc-langs-rust/src/test/resources/passing/Cargo.lock b/tmc-langs-rust/src/test/resources/passing/Cargo.lock deleted file mode 100644 index e887b01b3..000000000 --- a/tmc-langs-rust/src/test/resources/passing/Cargo.lock +++ /dev/null @@ -1,4 +0,0 @@ -[root] -name = "passing_suite" -version = "0.1.0" - diff --git a/tmc-langs-rust/src/test/resources/passing/Cargo.toml b/tmc-langs-rust/src/test/resources/passing/Cargo.toml index bf8600aa7..d1df12ba9 100644 --- a/tmc-langs-rust/src/test/resources/passing/Cargo.toml +++ b/tmc-langs-rust/src/test/resources/passing/Cargo.toml @@ -1,4 +1,4 @@ [package] -name = "passing_suite" +name = "passing" version = "0.1.0" -authors = [""] +authors = ["Example"] diff --git a/tmc-langs-rust/src/test/resources/passing/tests/mod.rs b/tmc-langs-rust/src/test/resources/passing/tests/mod.rs index 8f8088a28..04e1d4d95 100644 --- a/tmc-langs-rust/src/test/resources/passing/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/passing/tests/mod.rs @@ -1,7 +1,6 @@ -extern crate passing_suite; -use passing_suite::mul_xor_add; +extern crate passing; #[test] fn it_shall_work() { - assert_eq!(9, mul_xor_add(2, 3)); + assert_eq!(9, passing::mul_xor_add(2, 3)); } \ No newline at end of file From 8ee8782364bde123deca112840ada56d88333808 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Fri, 4 Sep 2015 11:27:06 +0300 Subject: [PATCH 03/13] Added failing test case and improved passing one. Fixed bugs in test result parsing. --- .../cs/tmc/langs/rust/CargoPlugin.java | 35 ++++------ .../cs/tmc/langs/rust/CargoResultParser.java | 67 ++++++++++--------- .../langs/rust/CargoStudentFilePolicy.java | 1 + .../cs/tmc/langs/rust/CargoPluginTest.java | 16 ++++- .../src/test/resources/failing/Cargo.lock | 4 ++ .../src/test/resources/failing/Cargo.toml | 4 ++ .../src/test/resources/failing/src/lib.rs | 5 ++ .../src/test/resources/failing/tests/mod.rs | 6 ++ 8 files changed, 82 insertions(+), 56 deletions(-) create mode 100644 tmc-langs-rust/src/test/resources/failing/Cargo.lock create mode 100644 tmc-langs-rust/src/test/resources/failing/Cargo.toml create mode 100644 tmc-langs-rust/src/test/resources/failing/src/lib.rs create mode 100644 tmc-langs-rust/src/test/resources/failing/tests/mod.rs diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java index a5e94a575..07b3f2d19 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java @@ -1,9 +1,6 @@ package fi.helsinki.cs.tmc.langs.rust; -import com.google.common.base.Function; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; + import fi.helsinki.cs.tmc.langs.AbstractLanguagePlugin; import fi.helsinki.cs.tmc.langs.abstraction.ValidationResult; import fi.helsinki.cs.tmc.langs.domain.Configuration; @@ -15,28 +12,23 @@ import fi.helsinki.cs.tmc.langs.domain.TestResult; 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.rust.util.Constants; import fi.helsinki.cs.tmc.langs.utils.ProcessResult; import fi.helsinki.cs.tmc.langs.utils.ProcessRunner; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javafx.concurrent.Worker; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class CargoPlugin extends AbstractLanguagePlugin { @@ -74,6 +66,10 @@ public String getLanguageName() { return "cargo"; } + public String getPluginName() { + return "cargo"; + } + @Override public Optional scanExercise(Path path, String exerciseName) { throw new UnsupportedOperationException("Not supported yet."); @@ -107,10 +103,7 @@ private RunResult runBuiltTests(Path dir) { log.info("Running tests with command {0}", Arrays.deepToString(command)); Optional result = run(command, dir); if (result.isPresent()) { - if (result.get().statusCode == 0) { - return parseResult(result.get(), dir); - } - return filledFailure(result.get()); + return parseResult(result.get(), dir); } return EMPTY_FAILURE; } diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java index e7c3d5de4..38ae71e8f 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -1,18 +1,20 @@ package fi.helsinki.cs.tmc.langs.rust; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import fi.helsinki.cs.tmc.langs.domain.RunResult; import fi.helsinki.cs.tmc.langs.domain.RunResult.Status; import fi.helsinki.cs.tmc.langs.domain.TestResult; import fi.helsinki.cs.tmc.langs.utils.ProcessResult; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -30,24 +32,27 @@ public class CargoResultParser { private static final Pattern RESULT = Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); public RunResult parse(ProcessResult processResult) { - String[] lines = processResult.output.split("\\r?\\n"); - String last = lines[lines.length - 1]; - Matcher matcher = RESULT.matcher(last); - if (matcher.matches()) { + String output = processResult.output; + String[] lines = output.split("\\r?\\n"); + + Matcher matcher = RESULT.matcher(output); + while (matcher.find()) { int fails = Integer.parseInt(matcher.group("fails")); int passes = Integer.parseInt(matcher.group("passes")); - int total = fails + passes; - Optional> failures - = findFailures(processResult.errorOutput, fails); - if (failures.isPresent()) { - Status status = fails == 0 ? Status.PASSED : Status.TESTS_FAILED; - Optional> tests = parseResults(lines, total); - if (tests.isPresent()) { - return new RunResult( - status, - buildTestResults(tests.get(), failures.get()), - ImmutableMap.of()); + if (fails + passes > 0) { + Optional> failures + = findFailures(processResult.output, fails); + if (failures.isPresent()) { + Status status = fails == 0 ? Status.PASSED : Status.TESTS_FAILED; + Optional> tests = parseResults(lines); + if (tests.isPresent()) { + return new RunResult( + status, + buildTestResults(tests.get(), failures.get()), + ImmutableMap.of()); + } } + break; } } return PARSING_FAILED; @@ -56,31 +61,27 @@ public RunResult parse(ProcessResult processResult) { //test test::dim4::test_4d_1_80_perioditic ... ok private static final Pattern TEST = Pattern.compile("test (?.*) \\.\\.\\. .*"); - private Optional> parseResults(String[] lines, int tests) { + private Optional> parseResults(String[] lines) { List result = new ArrayList<>(); - for (int n = 3; n < 3 + tests; n++) { - Matcher matcher = TEST.matcher(lines[n]); + for (String line : lines) { + Matcher matcher = TEST.matcher(line); if (matcher.matches()) { result.add(matcher.group("name")); - } else { - return Optional.absent(); } } return Optional.of(result); } //thread 'test::dim2::test_2d_1_80_normal' panicked at 'assertion failed: false', src\test\dim2.rs:12 - private static final Pattern FAILURES = Pattern.compile("thread '(?.*)' panicked at '(?.*)', .*"); + private static final Pattern FAILURES = Pattern.compile(".*thread '(?.*)' panicked at '(?.*)', .*"); private Optional> findFailures(String errorOutput, int fails) { Map result = new HashMap<>(); - String[] lines = errorOutput.split(System.lineSeparator()); - for (int n = lines.length - 1; n > lines.length - fails - 1; n--) { - Matcher matcher = FAILURES.matcher(lines[n]); + String[] lines = errorOutput.split("\\r?\\n"); + for (String line : lines) { + Matcher matcher = FAILURES.matcher(line); if (matcher.matches()) { result.put(matcher.group("name"), matcher.group("description")); - } else { - return Optional.absent(); } } return Optional.of(result); @@ -90,14 +91,14 @@ private ImmutableList buildTestResults(List results, Map testResults = ImmutableList.builder(); for (String test : results) { String description = failures.get(test); - boolean fail = true; + boolean pass = false; if (description == null) { description = ""; - fail = false; + pass = true; } TestResult testResult = new TestResult( test, - fail, + pass, ImmutableList.of(), description, ImmutableList.of()); diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java index a9e64fc24..06b1f9a87 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicy.java @@ -2,6 +2,7 @@ import fi.helsinki.cs.tmc.langs.io.ConfigurableStudentFilePolicy; import fi.helsinki.cs.tmc.langs.rust.util.Constants; + import java.nio.file.Path; public class CargoStudentFilePolicy extends ConfigurableStudentFilePolicy { diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java index 1413fc710..030f9c8a1 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java @@ -29,7 +29,7 @@ public void setUp() { } @Test - public void isExerciseCorrectTypeDoesntBreakByDirectoryNamedCargoToml() throws IOException { + public void testIsExerciseCorrectTypeDoesntBreakByDirectoryNamedCargoToml() throws IOException { Path parent = Files.createTempDirectory("tmc-cargo-test"); Path cargoToml = parent.resolve("Cargo.toml"); Files.createDirectory(cargoToml); @@ -41,11 +41,23 @@ public void isExerciseCorrectTypeDoesntBreakByDirectoryNamedCargoToml() throws I } @Test - public void testMakeProjectWithPassingTestsCompilesAndPassesTests() { + public void testProjectWithPassingTestCompilesAndPassesTests() { Path path = TestUtils.getPath(getClass(), "passing"); RunResult result = cargoPlugin.runTests(path); assertEquals(RunResult.Status.PASSED, result.status); + assertEquals(1, result.testResults.size()); + assertTrue(result.testResults.get(0).passed); + } + + @Test + public void testProjectWithFailingTestCompilesAndFailsTest() { + Path path = TestUtils.getPath(getClass(), "failing"); + RunResult result = cargoPlugin.runTests(path); + + assertEquals(RunResult.Status.TESTS_FAILED, result.status); + assertEquals(1, result.testResults.size()); + assertFalse(result.testResults.get(0).passed); } } diff --git a/tmc-langs-rust/src/test/resources/failing/Cargo.lock b/tmc-langs-rust/src/test/resources/failing/Cargo.lock new file mode 100644 index 000000000..c1a3e6151 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/failing/Cargo.lock @@ -0,0 +1,4 @@ +[root] +name = "failing" +version = "0.1.0" + diff --git a/tmc-langs-rust/src/test/resources/failing/Cargo.toml b/tmc-langs-rust/src/test/resources/failing/Cargo.toml new file mode 100644 index 000000000..eefa3d34c --- /dev/null +++ b/tmc-langs-rust/src/test/resources/failing/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "failing" +version = "0.1.0" +authors = ["Example"] diff --git a/tmc-langs-rust/src/test/resources/failing/src/lib.rs b/tmc-langs-rust/src/test/resources/failing/src/lib.rs new file mode 100644 index 000000000..c7770c937 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/failing/src/lib.rs @@ -0,0 +1,5 @@ + +pub fn mul_xor_add(a: u64, b: u64) -> u64 { + let x = a * b; + (x ^ a) + (x ^ b) +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/failing/tests/mod.rs b/tmc-langs-rust/src/test/resources/failing/tests/mod.rs new file mode 100644 index 000000000..4c9313256 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/failing/tests/mod.rs @@ -0,0 +1,6 @@ +extern crate failing; + +#[test] +fn it_shall_work() { + assert_eq!(4, failing::mul_xor_add(2, 3)); +} \ No newline at end of file From 9977493e8f4bec574f77b04c43a24e60464e3d0a Mon Sep 17 00:00:00 2001 From: WaDelma Date: Fri, 4 Sep 2015 21:08:33 +0300 Subject: [PATCH 04/13] Added rust to travis. Refactored cargo parser. Added error logging to cargo plugin. --- .travis.yml | 4 ++++ .../fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java | 11 ++++++----- .../helsinki/cs/tmc/langs/rust/CargoResultParser.java | 10 ++++------ .../helsinki/cs/tmc/langs/rust/CargoPluginTest.java | 3 --- tmc-langs-rust/src/test/resources/failing/Cargo.lock | 4 ---- 5 files changed, 14 insertions(+), 18 deletions(-) delete mode 100644 tmc-langs-rust/src/test/resources/failing/Cargo.lock diff --git a/.travis.yml b/.travis.yml index c8e9cf7ff..441abb738 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,10 @@ addons: - valgrind - check - python3.4 +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 before_install: - mkdir $HOME/bin && ln -s $(which python3.4) $HOME/bin/python3 && export PATH="$HOME/bin:$PATH" script: diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java index 07b3f2d19..9d186231c 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java @@ -1,6 +1,5 @@ package fi.helsinki.cs.tmc.langs.rust; - import fi.helsinki.cs.tmc.langs.AbstractLanguagePlugin; import fi.helsinki.cs.tmc.langs.abstraction.ValidationResult; import fi.helsinki.cs.tmc.langs.domain.Configuration; @@ -113,6 +112,7 @@ private Optional run(String[] command, Path dir) { try { return Optional.of(runner.call()); } catch (Exception e) { + log.error("Running command failed {0}", e); return Optional.absent(); } } @@ -120,13 +120,14 @@ private Optional run(String[] command, Path dir) { private RunResult filledFailure(ProcessResult processResult) { byte[] output = processResult.output.getBytes(StandardCharsets.UTF_8); byte[] errorOutput = processResult.errorOutput.getBytes(StandardCharsets.UTF_8); - ImmutableMap.Builder logs = new ImmutableMap.Builder<>(); - logs.put(SpecialLogs.STDOUT, output); - logs.put(SpecialLogs.STDERR, errorOutput); + ImmutableMap logs = new ImmutableMap.Builder() + .put(SpecialLogs.STDOUT, output) + .put(SpecialLogs.STDERR, errorOutput) + .build(); return new RunResult( Status.COMPILE_FAILED, ImmutableList.of(), - logs.build()); + logs); } private RunResult parseResult(ProcessResult processResult, Path path) { diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java index 38ae71e8f..9d08f7bc3 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -30,6 +30,10 @@ public class CargoResultParser { //test result: FAILED. 25 passed; 1 failed; 0 ignored; 0 measured private static final Pattern RESULT = Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); + //test test::dim4::test_4d_1_80_perioditic ... ok + private static final Pattern TEST = Pattern.compile("test (?.*) \\.\\.\\. .*"); + //thread 'test::dim2::test_2d_1_80_normal' panicked at 'assertion failed: false', src\test\dim2.rs:12 + private static final Pattern FAILURES = Pattern.compile(".*thread '(?.*)' panicked at '(?.*)', .*"); public RunResult parse(ProcessResult processResult) { String output = processResult.output; @@ -58,9 +62,6 @@ public RunResult parse(ProcessResult processResult) { return PARSING_FAILED; } - //test test::dim4::test_4d_1_80_perioditic ... ok - private static final Pattern TEST = Pattern.compile("test (?.*) \\.\\.\\. .*"); - private Optional> parseResults(String[] lines) { List result = new ArrayList<>(); for (String line : lines) { @@ -72,9 +73,6 @@ private Optional> parseResults(String[] lines) { return Optional.of(result); } - //thread 'test::dim2::test_2d_1_80_normal' panicked at 'assertion failed: false', src\test\dim2.rs:12 - private static final Pattern FAILURES = Pattern.compile(".*thread '(?.*)' panicked at '(?.*)', .*"); - private Optional> findFailures(String errorOutput, int fails) { Map result = new HashMap<>(); String[] lines = errorOutput.split("\\r?\\n"); diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java index 030f9c8a1..74f50f85a 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java @@ -20,9 +20,6 @@ public class CargoPluginTest { private CargoPlugin cargoPlugin; - public CargoPluginTest() { - } - @Before public void setUp() { cargoPlugin = new CargoPlugin(); diff --git a/tmc-langs-rust/src/test/resources/failing/Cargo.lock b/tmc-langs-rust/src/test/resources/failing/Cargo.lock deleted file mode 100644 index c1a3e6151..000000000 --- a/tmc-langs-rust/src/test/resources/failing/Cargo.lock +++ /dev/null @@ -1,4 +0,0 @@ -[root] -name = "failing" -version = "0.1.0" - From 282b37146a96589c4f15684eaf98f52e059baf58 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Sat, 5 Sep 2015 20:54:47 +0300 Subject: [PATCH 05/13] Added a test. --- .../fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java | 10 ++++++++++ tmc-langs-rust/src/test/resources/testCheat/Cargo.lock | 4 ++++ tmc-langs-rust/src/test/resources/testCheat/Cargo.toml | 4 ++++ tmc-langs-rust/src/test/resources/testCheat/src/lib.rs | 9 +++++++++ .../src/test/resources/testCheat/tests/mod.rs | 6 ++++++ 5 files changed, 33 insertions(+) create mode 100644 tmc-langs-rust/src/test/resources/testCheat/Cargo.lock create mode 100644 tmc-langs-rust/src/test/resources/testCheat/Cargo.toml create mode 100644 tmc-langs-rust/src/test/resources/testCheat/src/lib.rs create mode 100644 tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java index 74f50f85a..e1fc28578 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java @@ -56,5 +56,15 @@ public void testProjectWithFailingTestCompilesAndFailsTest() { assertEquals(1, result.testResults.size()); assertFalse(result.testResults.get(0).passed); } + + @Test + public void testTryingToCheatByAddingTestFails() { + Path path = TestUtils.getPath(getClass(), "testCheat"); + RunResult result = cargoPlugin.runTests(path); + + assertEquals(RunResult.Status.TESTS_FAILED, result.status); + assertEquals(1, result.testResults.size()); + assertFalse(result.testResults.get(0).passed); + } } diff --git a/tmc-langs-rust/src/test/resources/testCheat/Cargo.lock b/tmc-langs-rust/src/test/resources/testCheat/Cargo.lock new file mode 100644 index 000000000..3bcc96fd3 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/testCheat/Cargo.lock @@ -0,0 +1,4 @@ +[root] +name = "test_cheat" +version = "0.1.0" + diff --git a/tmc-langs-rust/src/test/resources/testCheat/Cargo.toml b/tmc-langs-rust/src/test/resources/testCheat/Cargo.toml new file mode 100644 index 000000000..4bd1450aa --- /dev/null +++ b/tmc-langs-rust/src/test/resources/testCheat/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "test_cheat" +version = "0.1.0" +authors = ["Example"] diff --git a/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs b/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs new file mode 100644 index 000000000..1863bb479 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs @@ -0,0 +1,9 @@ + +pub fn mul_xor_add(a: u64, b: u64) -> u64 { + a + b +} + +#[test] +fn it_shall_work() { + +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs b/tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs new file mode 100644 index 000000000..7e95fddbe --- /dev/null +++ b/tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs @@ -0,0 +1,6 @@ +extern crate test_cheat; + +#[test] +fn it_shall_work() { + assert_eq!(9, test_cheat::mul_xor_add(2, 3)); +} \ No newline at end of file From 84102796efe243e4624957f5956861685589fd95 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Sun, 6 Sep 2015 03:20:17 +0300 Subject: [PATCH 06/13] Added tests and fixed problems unveiled by them. --- .../cs/tmc/langs/rust/CargoPlugin.java | 8 +-- .../cs/tmc/langs/rust/CargoResultParser.java | 8 ++- .../cs/tmc/langs/rust/CargoPluginTest.java | 40 ++++++++++- .../tmc/langs/rust/CargoResultParserTest.java | 68 +++++++++++++++++++ .../src/test/resources/compileFail/Cargo.toml | 4 ++ .../src/test/resources/compileFail/src/lib.rs | 5 ++ .../test/resources/compileFail/tests/mod.rs | 6 ++ .../src/test/resources/failing/src/lib.rs | 3 +- .../src/test/resources/failing/tests/mod.rs | 2 +- .../test/resources/multiPassing/Cargo.toml | 4 ++ .../test/resources/multiPassing/src/lib.rs | 5 ++ .../test/resources/multiPassing/tests/mod.rs | 11 +++ .../src/test/resources/semiFailing/Cargo.toml | 4 ++ .../src/test/resources/semiFailing/src/lib.rs | 4 ++ .../test/resources/semiFailing/tests/mod.rs | 11 +++ .../src/test/resources/testCheat/Cargo.lock | 4 -- 16 files changed, 173 insertions(+), 14 deletions(-) create mode 100644 tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java create mode 100644 tmc-langs-rust/src/test/resources/compileFail/Cargo.toml create mode 100644 tmc-langs-rust/src/test/resources/compileFail/src/lib.rs create mode 100644 tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs create mode 100644 tmc-langs-rust/src/test/resources/multiPassing/Cargo.toml create mode 100644 tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs create mode 100644 tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs create mode 100644 tmc-langs-rust/src/test/resources/semiFailing/Cargo.toml create mode 100644 tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs create mode 100644 tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs delete mode 100644 tmc-langs-rust/src/test/resources/testCheat/Cargo.lock diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java index 9d186231c..67b62d992 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java @@ -84,10 +84,10 @@ public RunResult runTests(Path path) { return runBuiltTests(path); } - private Optional build(Path dir) { + private Optional build(Path path) { String[] command = {"cargo", "test", "--no-run"}; log.info("Building project with command {0}", Arrays.deepToString(command)); - Optional result = run(command, dir); + Optional result = run(command, path); if (result.isPresent()) { if (result.get().statusCode == 0) { return Optional.absent(); @@ -118,11 +118,9 @@ private Optional run(String[] command, Path dir) { } private RunResult filledFailure(ProcessResult processResult) { - byte[] output = processResult.output.getBytes(StandardCharsets.UTF_8); byte[] errorOutput = processResult.errorOutput.getBytes(StandardCharsets.UTF_8); ImmutableMap logs = new ImmutableMap.Builder() - .put(SpecialLogs.STDOUT, output) - .put(SpecialLogs.STDERR, errorOutput) + .put(SpecialLogs.COMPILER_OUTPUT, errorOutput) .build(); return new RunResult( Status.COMPILE_FAILED, diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java index 9d08f7bc3..fc2572a6e 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -8,6 +8,7 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -53,7 +54,12 @@ public RunResult parse(ProcessResult processResult) { return new RunResult( status, buildTestResults(tests.get(), failures.get()), - ImmutableMap.of()); + new ImmutableMap.Builder() + .put(SpecialLogs.STDOUT, + processResult.output.getBytes(StandardCharsets.UTF_8)) + .put(SpecialLogs.STDERR, + processResult.errorOutput.getBytes(StandardCharsets.UTF_8)) + .build()); } } break; diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java index e1fc28578..277d4a724 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java @@ -4,6 +4,7 @@ import fi.helsinki.cs.tmc.langs.abstraction.ValidationResult; import fi.helsinki.cs.tmc.langs.domain.ExerciseDesc; import fi.helsinki.cs.tmc.langs.domain.RunResult; +import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; import fi.helsinki.cs.tmc.langs.io.StudentFilePolicy; import fi.helsinki.cs.tmc.langs.utils.TestUtils; import java.io.IOException; @@ -15,6 +16,7 @@ import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; +import org.junit.Ignore; public class CargoPluginTest { @@ -47,6 +49,17 @@ public void testProjectWithPassingTestCompilesAndPassesTests() { assertTrue(result.testResults.get(0).passed); } + @Test + public void testProjectWithMultiplePassingTestCompilesAndPassesTests() { + Path path = TestUtils.getPath(getClass(), "multiPassing"); + RunResult result = cargoPlugin.runTests(path); + + assertEquals(RunResult.Status.PASSED, result.status); + assertEquals(2, result.testResults.size()); + assertTrue(result.testResults.get(0).passed); + assertTrue(result.testResults.get(1).passed); + } + @Test public void testProjectWithFailingTestCompilesAndFailsTest() { Path path = TestUtils.getPath(getClass(), "failing"); @@ -56,7 +69,22 @@ public void testProjectWithFailingTestCompilesAndFailsTest() { assertEquals(1, result.testResults.size()); assertFalse(result.testResults.get(0).passed); } - + + @Test + public void testProjectPartiallyFailingTestCompilesAndFailsTest() { + Path path = TestUtils.getPath(getClass(), "semiFailing"); + RunResult result = cargoPlugin.runTests(path); + + assertEquals(RunResult.Status.TESTS_FAILED, result.status); + assertEquals(2, result.testResults.size()); + boolean first = result.testResults.get(0).passed; + if (first) { + assertFalse(result.testResults.get(1).passed); + } else { + assertTrue(result.testResults.get(1).passed); + } + } + @Test public void testTryingToCheatByAddingTestFails() { Path path = TestUtils.getPath(getClass(), "testCheat"); @@ -67,4 +95,14 @@ public void testTryingToCheatByAddingTestFails() { assertFalse(result.testResults.get(0).passed); } + @Test + public void compilationFailurePreserversCompilationOutput() { + Path path = TestUtils.getPath(getClass(), "compileFail"); + RunResult result = cargoPlugin.runTests(path); + + assertEquals(RunResult.Status.COMPILE_FAILED, result.status); + assertTrue(result.logs.containsKey(SpecialLogs.COMPILER_OUTPUT)); + assertTrue(new String(result.logs.get(SpecialLogs.COMPILER_OUTPUT)).contains("aborting due to previous error")); + assertEquals(0, result.testResults.size()); + } } diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java new file mode 100644 index 000000000..132ffb134 --- /dev/null +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java @@ -0,0 +1,68 @@ +package fi.helsinki.cs.tmc.langs.rust; + +import fi.helsinki.cs.tmc.langs.domain.RunResult; +import fi.helsinki.cs.tmc.langs.domain.RunResult.Status; +import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; +import fi.helsinki.cs.tmc.langs.utils.ProcessResult; +import javafx.concurrent.Worker; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +public class CargoResultParserTest { + + private CargoResultParser parser; + private String fail; + + @Before + public void setUp() { + parser = new CargoResultParser(); + + StringBuilder builder = new StringBuilder(); + builder.append(" Compiling example version (path)\n"); + builder.append(" Running target\\debug\\mod-hash.exe\n"); + builder.append("\n"); + builder.append("running 1 test\n"); + builder.append("test name ... FAILED\n"); + builder.append("\n"); + builder.append("failures:\n"); + builder.append("\n"); + builder.append("---- name stdout ----\n"); + builder.append(" thread 'name' panicked at 'description', tests\\mod.rs:line\n"); + builder.append("\n"); + builder.append("\n"); + builder.append("failures:\n"); + builder.append(" name\n"); + builder.append("\n"); + builder.append("test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured"); + fail = builder.toString(); + } + + @Test + public void failFails() { + ProcessResult result = new ProcessResult(0, fail, ""); + RunResult parsed = parser.parse(result); + assertEquals(Status.TESTS_FAILED, parsed.status); + } + + @Test + public void failContainsRightResult() { + ProcessResult result = new ProcessResult(0, fail, ""); + RunResult parsed = parser.parse(result); + assertEquals(1, parsed.testResults.size()); + assertEquals("description", parsed.testResults.get(0).errorMessage); + assertEquals("name", parsed.testResults.get(0).name); + assertEquals(false, parsed.testResults.get(0).passed); + } + + @Test + public void failPreservesStdout() { + ProcessResult result = new ProcessResult(0, fail, ""); + RunResult parsed = parser.parse(result); + assertTrue(parsed.logs.containsKey(SpecialLogs.STDOUT)); + assertEquals(fail, new String(parsed.logs.get(SpecialLogs.STDOUT))); + } +} diff --git a/tmc-langs-rust/src/test/resources/compileFail/Cargo.toml b/tmc-langs-rust/src/test/resources/compileFail/Cargo.toml new file mode 100644 index 000000000..d1df12ba9 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/compileFail/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "passing" +version = "0.1.0" +authors = ["Example"] diff --git a/tmc-langs-rust/src/test/resources/compileFail/src/lib.rs b/tmc-langs-rust/src/test/resources/compileFail/src/lib.rs new file mode 100644 index 000000000..e3669315c --- /dev/null +++ b/tmc-langs-rust/src/test/resources/compileFail/src/lib.rs @@ -0,0 +1,5 @@ + +pub fn mul_xor_add(a: u64, b: u64) -> u64 { + let x = a * b; + (x ^ a) + (x ^ b); +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs b/tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs new file mode 100644 index 000000000..04e1d4d95 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs @@ -0,0 +1,6 @@ +extern crate passing; + +#[test] +fn it_shall_work() { + assert_eq!(9, passing::mul_xor_add(2, 3)); +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/failing/src/lib.rs b/tmc-langs-rust/src/test/resources/failing/src/lib.rs index c7770c937..c7e1dbdc0 100644 --- a/tmc-langs-rust/src/test/resources/failing/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/failing/src/lib.rs @@ -1,5 +1,4 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { - let x = a * b; - (x ^ a) + (x ^ b) + a + b } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/failing/tests/mod.rs b/tmc-langs-rust/src/test/resources/failing/tests/mod.rs index 4c9313256..41f34dc72 100644 --- a/tmc-langs-rust/src/test/resources/failing/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/failing/tests/mod.rs @@ -2,5 +2,5 @@ extern crate failing; #[test] fn it_shall_work() { - assert_eq!(4, failing::mul_xor_add(2, 3)); + assert_eq!(9, failing::mul_xor_add(2, 3)); } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/multiPassing/Cargo.toml b/tmc-langs-rust/src/test/resources/multiPassing/Cargo.toml new file mode 100644 index 000000000..d1df12ba9 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/multiPassing/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "passing" +version = "0.1.0" +authors = ["Example"] diff --git a/tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs b/tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs new file mode 100644 index 000000000..c7770c937 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs @@ -0,0 +1,5 @@ + +pub fn mul_xor_add(a: u64, b: u64) -> u64 { + let x = a * b; + (x ^ a) + (x ^ b) +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs b/tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs new file mode 100644 index 000000000..072ba0db0 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs @@ -0,0 +1,11 @@ +extern crate passing; + +#[test] +fn it_shall_work() { + assert_eq!(9, passing::mul_xor_add(2, 3)); +} + +#[test] +fn it_shall_work2() { + assert_eq!(5, passing::mul_xor_add(1, 4)); +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/semiFailing/Cargo.toml b/tmc-langs-rust/src/test/resources/semiFailing/Cargo.toml new file mode 100644 index 000000000..eefa3d34c --- /dev/null +++ b/tmc-langs-rust/src/test/resources/semiFailing/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "failing" +version = "0.1.0" +authors = ["Example"] diff --git a/tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs b/tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs new file mode 100644 index 000000000..c7e1dbdc0 --- /dev/null +++ b/tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs @@ -0,0 +1,4 @@ + +pub fn mul_xor_add(a: u64, b: u64) -> u64 { + a + b +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs b/tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs new file mode 100644 index 000000000..036c4977b --- /dev/null +++ b/tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs @@ -0,0 +1,11 @@ +extern crate failing; + +#[test] +fn it_shall_work() { + assert_eq!(9, failing::mul_xor_add(2, 3)); +} + +#[test] +fn it_shall_work2() { + assert_eq!(5, failing::mul_xor_add(1, 4)); +} \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/testCheat/Cargo.lock b/tmc-langs-rust/src/test/resources/testCheat/Cargo.lock deleted file mode 100644 index 3bcc96fd3..000000000 --- a/tmc-langs-rust/src/test/resources/testCheat/Cargo.lock +++ /dev/null @@ -1,4 +0,0 @@ -[root] -name = "test_cheat" -version = "0.1.0" - From 68cef0541e6b9f90a57dd6bc76ee0603ac647e19 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Sun, 6 Sep 2015 03:34:51 +0300 Subject: [PATCH 07/13] Fixed bad import. Fixed some code style problems. Added some Javadoc. --- .../cs/tmc/langs/rust/CargoResultParser.java | 18 +++++++++++++----- .../cs/tmc/langs/rust/CargoPluginTest.java | 19 ++++++++----------- .../tmc/langs/rust/CargoResultParserTest.java | 11 +++++------ 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java index fc2572a6e..80f724e24 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -2,23 +2,25 @@ import fi.helsinki.cs.tmc.langs.domain.RunResult; import fi.helsinki.cs.tmc.langs.domain.RunResult.Status; +import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; import fi.helsinki.cs.tmc.langs.domain.TestResult; import fi.helsinki.cs.tmc.langs.utils.ProcessResult; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * Parses Cargos test output. + */ public class CargoResultParser { private static final RunResult PARSING_FAILED = new RunResult( @@ -30,12 +32,17 @@ public class CargoResultParser { .build()); //test result: FAILED. 25 passed; 1 failed; 0 ignored; 0 measured - private static final Pattern RESULT = Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); + private static final Pattern RESULT = + Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); //test test::dim4::test_4d_1_80_perioditic ... ok private static final Pattern TEST = Pattern.compile("test (?.*) \\.\\.\\. .*"); //thread 'test::dim2::test_2d_1_80_normal' panicked at 'assertion failed: false', src\test\dim2.rs:12 - private static final Pattern FAILURES = Pattern.compile(".*thread '(?.*)' panicked at '(?.*)', .*"); + private static final Pattern FAILURES = + Pattern.compile(".*thread '(?.*)' panicked at '(?.*)', .*"); + /** + * Parses given process results outputs to a run result. + */ public RunResult parse(ProcessResult processResult) { String output = processResult.output; String[] lines = output.split("\\r?\\n"); @@ -91,7 +98,8 @@ private Optional> findFailures(String errorOutput, int fails return Optional.of(result); } - private ImmutableList buildTestResults(List results, Map failures) { + private ImmutableListbuildTestResults(List results, + Map failures) { ImmutableList.Builder testResults = ImmutableList.builder(); for (String test : results) { String description = failures.get(test); diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java index 277d4a724..d4c38bad6 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java @@ -1,22 +1,19 @@ package fi.helsinki.cs.tmc.langs.rust; -import com.google.common.base.Optional; -import fi.helsinki.cs.tmc.langs.abstraction.ValidationResult; -import fi.helsinki.cs.tmc.langs.domain.ExerciseDesc; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import fi.helsinki.cs.tmc.langs.domain.RunResult; import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; -import fi.helsinki.cs.tmc.langs.io.StudentFilePolicy; import fi.helsinki.cs.tmc.langs.utils.TestUtils; + +import org.junit.Before; +import org.junit.Test; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.Ignore; public class CargoPluginTest { diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java index 132ffb134..fe7f7f4df 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java @@ -1,16 +1,15 @@ package fi.helsinki.cs.tmc.langs.rust; +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.RunResult.Status; import fi.helsinki.cs.tmc.langs.domain.SpecialLogs; import fi.helsinki.cs.tmc.langs.utils.ProcessResult; -import javafx.concurrent.Worker; -import org.junit.After; -import org.junit.AfterClass; + import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; -import static org.junit.Assert.*; public class CargoResultParserTest { @@ -31,7 +30,7 @@ public void setUp() { builder.append("failures:\n"); builder.append("\n"); builder.append("---- name stdout ----\n"); - builder.append(" thread 'name' panicked at 'description', tests\\mod.rs:line\n"); + builder.append("\tthread 'name' panicked at 'description', tests\\mod.rs:line\n"); builder.append("\n"); builder.append("\n"); builder.append("failures:\n"); From 348bfda7923b4d992a9d5856f6b956133df5f984 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Sun, 6 Sep 2015 20:04:24 +0300 Subject: [PATCH 08/13] Improved logging, Refactoring. --- .../cs/tmc/langs/rust/CargoPlugin.java | 2 +- .../cs/tmc/langs/rust/CargoResultParser.java | 36 +++++++++---------- .../rust/CargoStudentFilePolicyTest.java | 28 +++++++++++++++ 3 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java index 67b62d992..e1d62a37d 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java @@ -112,7 +112,7 @@ private Optional run(String[] command, Path dir) { try { return Optional.of(runner.call()); } catch (Exception e) { - log.error("Running command failed {0}", e); + log.error("Running command {0} failed {1}", Arrays.deepToString(command), e); return Optional.absent(); } } diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java index 80f724e24..9adb2e698 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -32,13 +32,13 @@ public class CargoResultParser { .build()); //test result: FAILED. 25 passed; 1 failed; 0 ignored; 0 measured - private static final Pattern RESULT = - Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); + private static final Pattern RESULT + = Pattern.compile("test result: .*\\. (?\\d*) passed; (?\\d*) failed; \\d* ignored; \\d* measured"); //test test::dim4::test_4d_1_80_perioditic ... ok private static final Pattern TEST = Pattern.compile("test (?.*) \\.\\.\\. .*"); //thread 'test::dim2::test_2d_1_80_normal' panicked at 'assertion failed: false', src\test\dim2.rs:12 - private static final Pattern FAILURES = - Pattern.compile(".*thread '(?.*)' panicked at '(?.*)', .*"); + private static final Pattern FAILURES + = Pattern.compile(".*thread '(?.*)' panicked at '(?.*)', .*"); /** * Parses given process results outputs to a run result. @@ -56,18 +56,16 @@ public RunResult parse(ProcessResult processResult) { = findFailures(processResult.output, fails); if (failures.isPresent()) { Status status = fails == 0 ? Status.PASSED : Status.TESTS_FAILED; - Optional> tests = parseResults(lines); - if (tests.isPresent()) { - return new RunResult( - status, - buildTestResults(tests.get(), failures.get()), - new ImmutableMap.Builder() - .put(SpecialLogs.STDOUT, - processResult.output.getBytes(StandardCharsets.UTF_8)) - .put(SpecialLogs.STDERR, - processResult.errorOutput.getBytes(StandardCharsets.UTF_8)) - .build()); - } + List tests = parseResults(lines); + return new RunResult( + status, + buildTestResults(tests, failures.get()), + new ImmutableMap.Builder() + .put(SpecialLogs.STDOUT, + processResult.output.getBytes(StandardCharsets.UTF_8)) + .put(SpecialLogs.STDERR, + processResult.errorOutput.getBytes(StandardCharsets.UTF_8)) + .build()); } break; } @@ -75,7 +73,7 @@ public RunResult parse(ProcessResult processResult) { return PARSING_FAILED; } - private Optional> parseResults(String[] lines) { + private List parseResults(String[] lines) { List result = new ArrayList<>(); for (String line : lines) { Matcher matcher = TEST.matcher(line); @@ -83,7 +81,7 @@ private Optional> parseResults(String[] lines) { result.add(matcher.group("name")); } } - return Optional.of(result); + return result; } private Optional> findFailures(String errorOutput, int fails) { @@ -98,7 +96,7 @@ private Optional> findFailures(String errorOutput, int fails return Optional.of(result); } - private ImmutableListbuildTestResults(List results, + private ImmutableList buildTestResults(List results, Map failures) { ImmutableList.Builder testResults = ImmutableList.builder(); for (String test : results) { diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java new file mode 100644 index 000000000..8deb08c35 --- /dev/null +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java @@ -0,0 +1,28 @@ +package fi.helsinki.cs.tmc.langs.rust; + +import static org.junit.Assert.*; + +import java.nio.file.Paths; + +import org.junit.Before; +import org.junit.Test; + + +public class CargoStudentFilePolicyTest { + private CargoStudentFilePolicy policy; + + @Before + public void setUp() { + policy = new CargoStudentFilePolicy(Paths.get("")); + } + + @Test + public void testCargoTomlIsNotStudentFile() { + assertFalse(policy.isStudentSourceFile(Paths.get("src/Cargo.toml"))); + } + + @Test + public void testSourceFileIsSourceFile() { + assertTrue(policy.isStudentSourceFile(Paths.get("src/hello.rs"))); + } +} From 3eac0b05e374ae7e6e077881e7b83e821eab8278 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Sun, 6 Sep 2015 20:05:55 +0300 Subject: [PATCH 09/13] Removed unused variable. --- .../src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java | 1 - 1 file changed, 1 deletion(-) diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java index e1d62a37d..4354b8dc9 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoPlugin.java @@ -129,7 +129,6 @@ private RunResult filledFailure(ProcessResult processResult) { } private RunResult parseResult(ProcessResult processResult, Path path) { - Configuration configuration = new Configuration(path); return new CargoResultParser().parse(processResult); } From 1544224252d8987be47e09731ff4604d3e213e45 Mon Sep 17 00:00:00 2001 From: WaDelma Date: Mon, 7 Sep 2015 13:12:43 +0300 Subject: [PATCH 10/13] Changed tests. Transformed tabs to spaces. --- .../tmc/langs/rust/CargoResultParserTest.java | 49 +++++++++---------- .../rust/CargoStudentFilePolicyTest.java | 10 ++-- .../src/test/resources/compileFail/src/lib.rs | 4 +- .../test/resources/compileFail/tests/mod.rs | 2 +- .../src/test/resources/failing/src/lib.rs | 2 +- .../src/test/resources/failing/tests/mod.rs | 2 +- .../test/resources/multiPassing/src/lib.rs | 4 +- .../test/resources/multiPassing/tests/mod.rs | 4 +- .../src/test/resources/passing/src/lib.rs | 4 +- .../src/test/resources/passing/tests/mod.rs | 2 +- .../src/test/resources/semiFailing/src/lib.rs | 2 +- .../test/resources/semiFailing/tests/mod.rs | 4 +- .../src/test/resources/testCheat/src/lib.rs | 2 +- .../src/test/resources/testCheat/tests/mod.rs | 2 +- 14 files changed, 45 insertions(+), 48 deletions(-) diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java index fe7f7f4df..a01d96714 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParserTest.java @@ -14,43 +14,41 @@ public class CargoResultParserTest { private CargoResultParser parser; - private String fail; + private final String fail = new StringBuilder() + .append(" Compiling example version (path)\n") + .append(" Running target\\debug\\mod-hash.exe\n") + .append("\n") + .append("running 1 test\n") + .append("test name ... FAILED\n") + .append("\n") + .append("failures:\n") + .append("\n") + .append("---- name stdout ----\n") + .append("\tthread 'name' panicked at 'description', tests\\mod.rs:line\n") + .append("\n") + .append("\n") + .append("failures:\n") + .append(" name\n") + .append("\n") + .append("test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured") + .toString(); + private ProcessResult failResult; @Before public void setUp() { parser = new CargoResultParser(); - - StringBuilder builder = new StringBuilder(); - builder.append(" Compiling example version (path)\n"); - builder.append(" Running target\\debug\\mod-hash.exe\n"); - builder.append("\n"); - builder.append("running 1 test\n"); - builder.append("test name ... FAILED\n"); - builder.append("\n"); - builder.append("failures:\n"); - builder.append("\n"); - builder.append("---- name stdout ----\n"); - builder.append("\tthread 'name' panicked at 'description', tests\\mod.rs:line\n"); - builder.append("\n"); - builder.append("\n"); - builder.append("failures:\n"); - builder.append(" name\n"); - builder.append("\n"); - builder.append("test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured"); - fail = builder.toString(); + failResult = new ProcessResult(0, fail, ""); } @Test public void failFails() { - ProcessResult result = new ProcessResult(0, fail, ""); - RunResult parsed = parser.parse(result); + RunResult parsed = parser.parse(failResult); assertEquals(Status.TESTS_FAILED, parsed.status); } @Test public void failContainsRightResult() { - ProcessResult result = new ProcessResult(0, fail, ""); - RunResult parsed = parser.parse(result); + RunResult parsed = parser.parse(failResult); assertEquals(1, parsed.testResults.size()); assertEquals("description", parsed.testResults.get(0).errorMessage); assertEquals("name", parsed.testResults.get(0).name); @@ -59,8 +57,7 @@ public void failContainsRightResult() { @Test public void failPreservesStdout() { - ProcessResult result = new ProcessResult(0, fail, ""); - RunResult parsed = parser.parse(result); + RunResult parsed = parser.parse(failResult); assertTrue(parsed.logs.containsKey(SpecialLogs.STDOUT)); assertEquals(fail, new String(parsed.logs.get(SpecialLogs.STDOUT))); } diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java index 8deb08c35..1e53eeab6 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java @@ -7,10 +7,10 @@ import org.junit.Before; import org.junit.Test; - public class CargoStudentFilePolicyTest { + private CargoStudentFilePolicy policy; - + @Before public void setUp() { policy = new CargoStudentFilePolicy(Paths.get("")); @@ -18,11 +18,11 @@ public void setUp() { @Test public void testCargoTomlIsNotStudentFile() { - assertFalse(policy.isStudentSourceFile(Paths.get("src/Cargo.toml"))); + assertFalse(policy.isStudentSourceFile(Paths.get("src", "Cargo.toml"))); } - + @Test public void testSourceFileIsSourceFile() { - assertTrue(policy.isStudentSourceFile(Paths.get("src/hello.rs"))); + assertTrue(policy.isStudentSourceFile(Paths.get("src", "hello.rs"))); } } diff --git a/tmc-langs-rust/src/test/resources/compileFail/src/lib.rs b/tmc-langs-rust/src/test/resources/compileFail/src/lib.rs index e3669315c..801532dc7 100644 --- a/tmc-langs-rust/src/test/resources/compileFail/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/compileFail/src/lib.rs @@ -1,5 +1,5 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { - let x = a * b; - (x ^ a) + (x ^ b); + let x = a * b; + (x ^ a) + (x ^ b); } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs b/tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs index 04e1d4d95..5204e7f28 100644 --- a/tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/compileFail/tests/mod.rs @@ -2,5 +2,5 @@ extern crate passing; #[test] fn it_shall_work() { - assert_eq!(9, passing::mul_xor_add(2, 3)); + assert_eq!(9, passing::mul_xor_add(2, 3)); } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/failing/src/lib.rs b/tmc-langs-rust/src/test/resources/failing/src/lib.rs index c7e1dbdc0..3c3800cf8 100644 --- a/tmc-langs-rust/src/test/resources/failing/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/failing/src/lib.rs @@ -1,4 +1,4 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { - a + b + a + b } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/failing/tests/mod.rs b/tmc-langs-rust/src/test/resources/failing/tests/mod.rs index 41f34dc72..def1a4127 100644 --- a/tmc-langs-rust/src/test/resources/failing/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/failing/tests/mod.rs @@ -2,5 +2,5 @@ extern crate failing; #[test] fn it_shall_work() { - assert_eq!(9, failing::mul_xor_add(2, 3)); + assert_eq!(9, failing::mul_xor_add(2, 3)); } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs b/tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs index c7770c937..edc27f080 100644 --- a/tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/multiPassing/src/lib.rs @@ -1,5 +1,5 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { - let x = a * b; - (x ^ a) + (x ^ b) + let x = a * b; + (x ^ a) + (x ^ b) } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs b/tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs index 072ba0db0..69dcb92f1 100644 --- a/tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/multiPassing/tests/mod.rs @@ -2,10 +2,10 @@ extern crate passing; #[test] fn it_shall_work() { - assert_eq!(9, passing::mul_xor_add(2, 3)); + assert_eq!(9, passing::mul_xor_add(2, 3)); } #[test] fn it_shall_work2() { - assert_eq!(5, passing::mul_xor_add(1, 4)); + assert_eq!(5, passing::mul_xor_add(1, 4)); } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/passing/src/lib.rs b/tmc-langs-rust/src/test/resources/passing/src/lib.rs index c7770c937..edc27f080 100644 --- a/tmc-langs-rust/src/test/resources/passing/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/passing/src/lib.rs @@ -1,5 +1,5 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { - let x = a * b; - (x ^ a) + (x ^ b) + let x = a * b; + (x ^ a) + (x ^ b) } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/passing/tests/mod.rs b/tmc-langs-rust/src/test/resources/passing/tests/mod.rs index 04e1d4d95..5204e7f28 100644 --- a/tmc-langs-rust/src/test/resources/passing/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/passing/tests/mod.rs @@ -2,5 +2,5 @@ extern crate passing; #[test] fn it_shall_work() { - assert_eq!(9, passing::mul_xor_add(2, 3)); + assert_eq!(9, passing::mul_xor_add(2, 3)); } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs b/tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs index c7e1dbdc0..3c3800cf8 100644 --- a/tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/semiFailing/src/lib.rs @@ -1,4 +1,4 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { - a + b + a + b } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs b/tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs index 036c4977b..25aa54fca 100644 --- a/tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/semiFailing/tests/mod.rs @@ -2,10 +2,10 @@ extern crate failing; #[test] fn it_shall_work() { - assert_eq!(9, failing::mul_xor_add(2, 3)); + assert_eq!(9, failing::mul_xor_add(2, 3)); } #[test] fn it_shall_work2() { - assert_eq!(5, failing::mul_xor_add(1, 4)); + assert_eq!(5, failing::mul_xor_add(1, 4)); } \ No newline at end of file diff --git a/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs b/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs index 1863bb479..1aaa01243 100644 --- a/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs @@ -1,6 +1,6 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { - a + b + a + b } #[test] diff --git a/tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs b/tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs index 7e95fddbe..406a1864c 100644 --- a/tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs +++ b/tmc-langs-rust/src/test/resources/testCheat/tests/mod.rs @@ -2,5 +2,5 @@ extern crate test_cheat; #[test] fn it_shall_work() { - assert_eq!(9, test_cheat::mul_xor_add(2, 3)); + assert_eq!(9, test_cheat::mul_xor_add(2, 3)); } \ No newline at end of file From 3ce614673ae46ce2c8af1f96083580c7ebe5a023 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Sun, 13 Sep 2015 16:09:50 +0300 Subject: [PATCH 11/13] Moved rust installation in .travis.yml to before_install. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 441abb738..3a5e61f3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,11 +11,10 @@ addons: - valgrind - check - python3.4 -install: +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 -before_install: - mkdir $HOME/bin && ln -s $(which python3.4) $HOME/bin/python3 && export PATH="$HOME/bin:$PATH" script: - mvn checkstyle:check From 5ea8fdae5dbcf913928b661d9a7e485054cdb561 Mon Sep 17 00:00:00 2001 From: WaDelma Date: Sun, 13 Sep 2015 18:17:23 +0300 Subject: [PATCH 12/13] Added comment to clarify a test --- tmc-langs-rust/src/test/resources/testCheat/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs b/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs index 1aaa01243..2de43987a 100644 --- a/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs +++ b/tmc-langs-rust/src/test/resources/testCheat/src/lib.rs @@ -5,5 +5,5 @@ pub fn mul_xor_add(a: u64, b: u64) -> u64 { #[test] fn it_shall_work() { - -} \ No newline at end of file + //Muhahahaaa!!! Trying to cheat by adding same named test to confuse the system. +} From 2326b2ebbd79ce8d4bb994a601d972482eabf143 Mon Sep 17 00:00:00 2001 From: Wadelma Date: Sun, 13 Sep 2015 18:25:37 +0300 Subject: [PATCH 13/13] Refactoring and fixing style. --- .../cs/tmc/langs/rust/CargoResultParser.java | 32 ++++++++----------- .../cs/tmc/langs/rust/CargoPluginTest.java | 3 +- .../rust/CargoStudentFilePolicyTest.java | 7 ++-- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java index 9adb2e698..917881137 100644 --- a/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java +++ b/tmc-langs-rust/src/main/java/fi/helsinki/cs/tmc/langs/rust/CargoResultParser.java @@ -52,22 +52,18 @@ public RunResult parse(ProcessResult processResult) { int fails = Integer.parseInt(matcher.group("fails")); int passes = Integer.parseInt(matcher.group("passes")); if (fails + passes > 0) { - Optional> failures - = findFailures(processResult.output, fails); - if (failures.isPresent()) { - Status status = fails == 0 ? Status.PASSED : Status.TESTS_FAILED; - List tests = parseResults(lines); - return new RunResult( - status, - buildTestResults(tests, failures.get()), - new ImmutableMap.Builder() - .put(SpecialLogs.STDOUT, - processResult.output.getBytes(StandardCharsets.UTF_8)) - .put(SpecialLogs.STDERR, - processResult.errorOutput.getBytes(StandardCharsets.UTF_8)) - .build()); - } - break; + Map failures = findFailures(processResult.output, fails); + Status status = fails == 0 ? Status.PASSED : Status.TESTS_FAILED; + List tests = parseResults(lines); + return new RunResult( + status, + buildTestResults(tests, failures), + new ImmutableMap.Builder() + .put(SpecialLogs.STDOUT, + processResult.output.getBytes(StandardCharsets.UTF_8)) + .put(SpecialLogs.STDERR, + processResult.errorOutput.getBytes(StandardCharsets.UTF_8)) + .build()); } } return PARSING_FAILED; @@ -84,7 +80,7 @@ private List parseResults(String[] lines) { return result; } - private Optional> findFailures(String errorOutput, int fails) { + private Map findFailures(String errorOutput, int fails) { Map result = new HashMap<>(); String[] lines = errorOutput.split("\\r?\\n"); for (String line : lines) { @@ -93,7 +89,7 @@ private Optional> findFailures(String errorOutput, int fails result.put(matcher.group("name"), matcher.group("description")); } } - return Optional.of(result); + return result; } private ImmutableList buildTestResults(List results, diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java index d4c38bad6..2a9ea3799 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoPluginTest.java @@ -99,7 +99,8 @@ public void compilationFailurePreserversCompilationOutput() { assertEquals(RunResult.Status.COMPILE_FAILED, result.status); assertTrue(result.logs.containsKey(SpecialLogs.COMPILER_OUTPUT)); - assertTrue(new String(result.logs.get(SpecialLogs.COMPILER_OUTPUT)).contains("aborting due to previous error")); + assertTrue(new String(result.logs.get(SpecialLogs.COMPILER_OUTPUT)) + .contains("aborting due to previous error")); assertEquals(0, result.testResults.size()); } } diff --git a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java index 1e53eeab6..db60ab124 100644 --- a/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java +++ b/tmc-langs-rust/src/test/java/fi/helsinki/cs/tmc/langs/rust/CargoStudentFilePolicyTest.java @@ -1,12 +1,13 @@ package fi.helsinki.cs.tmc.langs.rust; -import static org.junit.Assert.*; - -import java.nio.file.Paths; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; +import java.nio.file.Paths; + public class CargoStudentFilePolicyTest { private CargoStudentFilePolicy policy;