From 0abbdd2ea9322ed209c5d025867f343484bd0eb5 Mon Sep 17 00:00:00 2001 From: Onni Aarne Date: Thu, 27 Jul 2017 17:36:14 +0300 Subject: [PATCH 1/2] Improve functionality for preparing tasks to be sent to sandbox --- .../fi/helsinki/cs/tmc/langs/cli/Main.java | 110 +++++++++++------- .../cs/tmc/langs/cli/JsonWriterTest.java | 2 +- .../cs/tmc/langs/util/TaskExecutor.java | 22 ++-- .../cs/tmc/langs/util/TaskExecutorImpl.java | 35 ++++-- .../tmc/langs/util/tarservice/TarCreator.java | 6 +- .../tmc/langs/util/TaskExecutorImplTest.java | 65 +++++++++++ 6 files changed, 173 insertions(+), 67 deletions(-) create mode 100644 tmc-langs-util/src/test/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImplTest.java diff --git a/tmc-langs-cli/src/main/java/fi/helsinki/cs/tmc/langs/cli/Main.java b/tmc-langs-cli/src/main/java/fi/helsinki/cs/tmc/langs/cli/Main.java index 3774a2718..42b9b6551 100644 --- a/tmc-langs-cli/src/main/java/fi/helsinki/cs/tmc/langs/cli/Main.java +++ b/tmc-langs-cli/src/main/java/fi/helsinki/cs/tmc/langs/cli/Main.java @@ -33,6 +33,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.logging.Level; /* * TODO: unstaticify this class @@ -44,7 +45,10 @@ public final class Main { private static final Logger logger = LoggerFactory.getLogger(Main.class); private static final String EXERCISE_PATH = "exercisePath"; + private static final String SUBMISSION_PATH = "submissionPath"; private static final String OUTPUT_PATH = "outputPath"; + private static final String TMC_RUN_PATH = "tmcRunPath"; + private static final String TMC_LANGS_PATH = "tmcLangsPath"; private static final String LOCALE = "locale"; @VisibleForTesting static Map argsMap = Maps.newHashMap(); @@ -62,8 +66,11 @@ public final class Main { + " Prepare a presentable solution from the original.\n" + " prepare-stubs --exercisePath -- outputPath" + " Prepare a stub exercise from the original.\n" - + " prepare-submission --clonePath --submissionPath --outputPath" - + " Prepares from submission and solution project for which the tests" + // TODO: Not implemented yet +// + " prepare-submission --exercisePath --submissionPath --outputPath" +// + " Prepares from submission and solution project for which the tests.\n" + + " prepare-sandbox-task --exercisePath --submissionPath --outputPath --tmcRunPath --tmcLangsPath" + + " Creates a tarball that sandbox can consume.\n" + " can be run in sandbox\n" + " run-tests --exercisePath --outputPath" + " Run the tests for the exercise.\n" @@ -138,6 +145,9 @@ private static void run(String command) { case "prepare-solutions": runPrepareSolutions(); break; + case "prepare-sandbox-task": + runPrepareSandboxTask(); + break; case "get-exercise-packaging-configuration": runGetExercisePackagingConfiguration(); break; @@ -157,6 +167,13 @@ private static Path getExercisePathFromArgs() { throw new IllegalStateException("No " + EXERCISE_PATH + " provided"); } + private static Path getSubmissionPathFromArgs() { + if (argsMap.containsKey(SUBMISSION_PATH)) { + return Paths.get(argsMap.get(SUBMISSION_PATH)); + } + throw new IllegalStateException("No " + SUBMISSION_PATH + " provided"); + } + private static Locale getLocaleFromArgs() { if (argsMap.containsKey(LOCALE)) { return new Locale(argsMap.get(LOCALE)); @@ -182,17 +199,28 @@ private static void runCompressProject() { } } + + private static Path getTmcRunPathFromArgs() { + if (argsMap.containsKey(TMC_RUN_PATH)) { + return Paths.get(argsMap.get(TMC_RUN_PATH)); + } + throw new IllegalStateException("No " + TMC_RUN_PATH + " provided"); + } + + private static Path getTmcLangsPathFromArgs() { + if (argsMap.containsKey(TMC_LANGS_PATH)) { + return Paths.get(argsMap.get(TMC_LANGS_PATH)); + } + throw new IllegalStateException("No " + TMC_LANGS_PATH + " provided"); + } + private static void runCheckCodeStyle() { ValidationResult validationResult = null; try { - validationResult = - executor.runCheckCodeStyle(getExercisePathFromArgs(), getLocaleFromArgs()); + validationResult = executor.runCheckCodeStyle(getExercisePathFromArgs(), getLocaleFromArgs()); } catch (NoLanguagePluginFoundException e) { - logger.error( - "No suitable language plugin for project at {}", getExercisePathFromArgs(), e); - printErrAndExit( - "ERROR: Could not find suitable language plugin for the given exercise " - + "path."); + logger.error("No suitable language plugin for project at {}", getExercisePathFromArgs(), e); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); } try { @@ -215,18 +243,13 @@ private static void runScanExercise() { printErrAndExit("ERROR: Could not scan the exercises."); } } catch (NoLanguagePluginFoundException e) { - logger.error( - "No suitable language plugin for project at {}", getExercisePathFromArgs(), e); - printErrAndExit( - "ERROR: Could not find suitable language plugin for the given " - + "exercise path."); + logger.error("No suitable language plugin for project at {}", getExercisePathFromArgs(), e); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); } try { JsonWriter.writeObjectIntoJsonFormat(exerciseDesc.get(), getOutputPathFromArgs()); - System.out.println( - "Exercises scanned successfully, results can be found in " - + getOutputPathFromArgs()); + System.out.println("Exercises scanned successfully, results can be found in " + getOutputPathFromArgs()); } catch (IOException e) { logger.error("Could not write output to {}", getOutputPathFromArgs(), e); printErrAndExit("ERROR: Could not write the results to the given file."); @@ -272,11 +295,8 @@ private static void runTests() { try { runResult = executor.runTests(getExercisePathFromArgs()); } catch (NoLanguagePluginFoundException e) { - logger.error( - "No suitable language plugin for project at {}", getExercisePathFromArgs(), e); - printErrAndExit( - "ERROR: Could not find suitable language plugin for the given " - + "exercise path."); + logger.error("No suitable language plugin for project at {}", getExercisePathFromArgs(), e); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); } try { @@ -295,11 +315,8 @@ private static void runPrepareStubs() { getExercisePathFromArgs(), getOutputPathFromArgs()); } catch (NoLanguagePluginFoundException e) { - logger.error( - "No suitable language plugin for project at {}", getExercisePathFromArgs(), e); - printErrAndExit( - "ERROR: Could not find suitable language plugin for the given " - + "exercise path."); + logger.error("No suitable language plugin for project at {}", getExercisePathFromArgs(), e); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); } } @@ -307,11 +324,8 @@ private static void runClean() { try { executor.clean(getExercisePathFromArgs()); } catch (NoLanguagePluginFoundException e) { - logger.error( - "No suitable language plugin for project at {}", getExercisePathFromArgs(), e); - printErrAndExit( - "ERROR: Could not find suitable language plugin for the given " - + "exercise path."); + logger.error("No suitable language plugin for project at {}", getExercisePathFromArgs(), e); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); } } @@ -354,11 +368,26 @@ private static void runPrepareSolutions() { getExercisePathFromArgs(), getOutputPathFromArgs()); } catch (NoLanguagePluginFoundException e) { - logger.error( - "No suitable language plugin for project at {}", getExercisePathFromArgs(), e); - printErrAndExit( - "ERROR: Could not find suitable language plugin for the given " - + "exercise path."); + logger.error("No suitable language plugin for project at {}", getExercisePathFromArgs(), e); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); + } + } + + private static void runPrepareSandboxTask() { + Path exercisePath = getExercisePathFromArgs(); + Path submissionPath = getSubmissionPathFromArgs(); + Path outputPath = getOutputPathFromArgs(); + Path tmcRunPath = getTmcRunPathFromArgs(); + Path tmcLangsPath = getTmcLangsPathFromArgs(); + + try { + executor.prepareSandboxTask(exercisePath, submissionPath, outputPath, tmcRunPath, tmcLangsPath); + } catch (NoLanguagePluginFoundException ex) { + logger.error("No suitable language plugin for project at {}", exercisePath, ex); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); + } catch (IOException e) { + logger.error("An error occurred while preparing task.", e); + printErrAndExit("ERROR: Could not prepare task."); } } @@ -367,11 +396,8 @@ private static void runGetExercisePackagingConfiguration() { try { configuration = executor.getExercisePackagingConfiguration(getExercisePathFromArgs()); } catch (NoLanguagePluginFoundException e) { - logger.error( - "No suitable language plugin for project at {}", getExercisePathFromArgs(), e); - printErrAndExit( - "ERROR: Could not find suitable language plugin for the given " - + "exercise path."); + logger.error("No suitable language plugin for project at {}", getExercisePathFromArgs(), e); + printErrAndExit("ERROR: Could not find suitable language plugin for the given exercise path."); } try { diff --git a/tmc-langs-cli/src/test/java/fi/helsinki/cs/tmc/langs/cli/JsonWriterTest.java b/tmc-langs-cli/src/test/java/fi/helsinki/cs/tmc/langs/cli/JsonWriterTest.java index 513fec9c4..ecb397989 100644 --- a/tmc-langs-cli/src/test/java/fi/helsinki/cs/tmc/langs/cli/JsonWriterTest.java +++ b/tmc-langs-cli/src/test/java/fi/helsinki/cs/tmc/langs/cli/JsonWriterTest.java @@ -46,4 +46,4 @@ public MockClass(String name) { } } } -} +} \ No newline at end of file diff --git a/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutor.java b/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutor.java index 69ab9f558..b157fe626 100644 --- a/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutor.java +++ b/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutor.java @@ -44,6 +44,15 @@ void prepareSolutions(Map exerciseMap, Path repoPath, Path */ void prepareStubs(Map exerciseMap, Path repoPath, Path destPath) throws NoLanguagePluginFoundException; + + /** + * Finds the correct language plug-in for the given exercise path. After which + * it copies all files from exercisePath and all student files from submissionPath + * and creates a tarball with the aforementioned files and tmc-langs, and tmc-run. + */ + public void prepareSandboxTask(Path exercisePath, Path submissionPath, + Path outputPath, Path tmcRunPath, Path tmcLangsPath) + throws NoLanguagePluginFoundException, IOException; /** * Finds the correct language plug-in for the given exercise path. After which calls the @@ -119,20 +128,9 @@ void extractProject(Path compressedProject, Path targetLocation, boolean overwri ExercisePackagingConfiguration getExercisePackagingConfiguration(Path path) throws NoLanguagePluginFoundException; - /** - * Creates a tarball that can be submitted to TMC-sandbox. - * The tar is created to the target location - * - * @param projectDir Location of the unzipped project - * @param tmcLangs Location of tmc-langs-cli.jar - * @param tmcrun Location of tmc-run init script - * @param targetLocation Location where the tar archive should be extracted to - */ - void compressTarForSubmitting(Path projectDir, Path tmcLangs, Path tmcrun, Path targetLocation) - throws IOException, ArchiveException; - /** * Run clean for given path using proper language plugin. */ void clean(Path path) throws NoLanguagePluginFoundException; + } diff --git a/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImpl.java b/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImpl.java index 24ea08283..331d9aaa0 100644 --- a/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImpl.java +++ b/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImpl.java @@ -16,13 +16,19 @@ import com.google.common.base.Optional; import org.apache.commons.compress.archivers.ArchiveException; + +import org.codehaus.plexus.util.FileUtils; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Locale; import java.util.Map; +import java.util.logging.Level; + public class TaskExecutorImpl implements TaskExecutor { @@ -106,7 +112,26 @@ public void prepareSolutions( throws NoLanguagePluginFoundException { new ExerciseBuilder().prepareSolutions(exerciseMap, repoPath, destPath); } - + + @Override + public void prepareSandboxTask(Path exercisePath, Path submissionPath, Path outputPath, + Path tmcRunPath, Path tmcLangsPath) + throws NoLanguagePluginFoundException, IOException { + Path tempdir = Files.createTempDirectory("sandbox-task"); + FileUtils.copyDirectoryStructure(exercisePath.toFile(), tempdir.toFile()); + getLanguagePlugin(exercisePath).prepareSubmission(submissionPath, tempdir); + TarCreator tarCreator = new TarCreator(); + log.info("Copying files to directory " + submissionPath.toString() + + " and creating tar ball"); + try { + tarCreator.createTarFromProject(tempdir, tmcLangsPath, tmcRunPath, outputPath); + } catch (ArchiveException ex) { + java.util.logging.Logger.getLogger(TaskExecutorImpl.class.getName()).log(Level.SEVERE, + "Failed to create tar from project " + submissionPath, ex); + } + FileUtils.forceDelete(tempdir.toFile()); + } + @Override public byte[] compressProject(Path path) throws NoLanguagePluginFoundException, IOException { return getLanguagePlugin(path).compressProject(path); @@ -118,14 +143,6 @@ public ExercisePackagingConfiguration getExercisePackagingConfiguration(Path pat return getLanguagePlugin(path).getExercisePackagingConfiguration(path); } - @Override - public void compressTarForSubmitting(Path projectDir, Path tmcLangs, - Path tmcrun, Path targetLocation) throws IOException, ArchiveException { - TarCreator tarCompresser = new TarCreator(); - log.info("Copying files to directory " + projectDir.toString() + " and creating tar ball"); - tarCompresser.createTarFromProject(projectDir, tmcLangs, tmcrun, targetLocation); - } - @Override public void clean(Path path) throws NoLanguagePluginFoundException { getLanguagePlugin(path).clean(path); diff --git a/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/tarservice/TarCreator.java b/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/tarservice/TarCreator.java index b8f20c8d7..5a896ead4 100644 --- a/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/tarservice/TarCreator.java +++ b/tmc-langs-util/src/main/java/fi/helsinki/cs/tmc/langs/util/tarservice/TarCreator.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; public class TarCreator { @@ -29,8 +30,8 @@ public class TarCreator { */ public void createTarFromProject(Path projectDir, Path tmcLangs, Path tmcrun, Path targetLocation) throws IOException, ArchiveException { - Files.copy(tmcrun, projectDir.resolve(tmcrun.getFileName())); - Files.copy(tmcLangs, projectDir.resolve(tmcLangs.getFileName())); + Files.copy(tmcrun, projectDir.resolve(Paths.get("tmc-run.sh"))); + Files.copy(tmcLangs, projectDir.resolve(Paths.get("tmc-langs.jar"))); createTarBall(projectDir, targetLocation); } @@ -58,7 +59,6 @@ private void createTarBall(Path project, Path targetLocation) * * @param folder The folder to add * @param tar TarArchiveOutputStreamer tar - * @param lengthOfPath The length of String from root until the start folder. * @throws FileNotFoundException Error! * @throws IOException Error! */ diff --git a/tmc-langs-util/src/test/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImplTest.java b/tmc-langs-util/src/test/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImplTest.java new file mode 100644 index 000000000..64c643841 --- /dev/null +++ b/tmc-langs-util/src/test/java/fi/helsinki/cs/tmc/langs/util/TaskExecutorImplTest.java @@ -0,0 +1,65 @@ +package fi.helsinki.cs.tmc.langs.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import fi.helsinki.cs.tmc.langs.domain.NoLanguagePluginFoundException; +import fi.helsinki.cs.tmc.langs.java.ant.AntPlugin; +import fi.helsinki.cs.tmc.langs.util.TaskExecutor; +import fi.helsinki.cs.tmc.langs.util.TaskExecutorImpl; +import fi.helsinki.cs.tmc.langs.utils.TestUtils; + +import org.apache.commons.compress.archivers.ArchiveException; +import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.LinkedList; +import java.util.List; + + +public class TaskExecutorImplTest { + + public TaskExecutorImplTest() { + TestUtils.skipIfNotAvailable("tar"); + } + + @Test + public void prepareSandboxTaskTest() throws IOException, NoLanguagePluginFoundException, + ArchiveException { + TaskExecutor executor = new TaskExecutorImpl(); + + Path exercisePath = TestUtils.getPath(getClass(), "arith_funcs"); + Path submissionPath = TestUtils.getPath(getClass(), "arith_funcs_solution"); + Path outputDirectory = Files.createTempDirectory("output-directory"); + Path outputPath = outputDirectory.resolve("output.tar"); + Path tmcRunPath = Files.createTempFile("fake-tmc-run", ".sh"); + Path tmcLangsPath = Files.createTempFile("fake-tmc-langs", ".jar"); + + executor.prepareSandboxTask(exercisePath, submissionPath, outputPath, tmcRunPath, tmcLangsPath); + Path testDirectory = Files.createTempDirectory("test-directory"); + + Process untarringProcess = new ProcessBuilder("tar", "-C", testDirectory.toString(), "-xf", + outputPath.toString()).start(); + + assertTrue(Files.exists(outputPath)); + assertTrue(Files.exists(testDirectory.resolve("tmc-langs.jar"))); + assertTrue(Files.exists(testDirectory.resolve("tmc-run.sh"))); + + FileUtils.forceDelete(outputDirectory.toFile()); + FileUtils.forceDelete(tmcRunPath.toFile()); + FileUtils.forceDelete(tmcLangsPath.toFile()); + FileUtils.forceDelete(testDirectory.toFile()); + } +} \ No newline at end of file From 62def5b7251695ce88f6b8294e837244dab104bf Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Mon, 18 Dec 2017 15:36:45 +0200 Subject: [PATCH 2/2] Update checkstyle max line length --- build-tools/src/main/resources/checkstyle/tmc-checkstyle.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-tools/src/main/resources/checkstyle/tmc-checkstyle.xml b/build-tools/src/main/resources/checkstyle/tmc-checkstyle.xml index 35c59a29e..a4d64773f 100644 --- a/build-tools/src/main/resources/checkstyle/tmc-checkstyle.xml +++ b/build-tools/src/main/resources/checkstyle/tmc-checkstyle.xml @@ -45,7 +45,7 @@ - + @@ -57,7 +57,7 @@ - +