From 9221b2ff22ba54d67498e9347e6cf098f6676fc7 Mon Sep 17 00:00:00 2001 From: Ellen Spertus Date: Mon, 4 Mar 2024 12:14:57 -0800 Subject: [PATCH] Make each Target a single file --- .../com/spertus/jacquard/common/Target.java | 71 +++++++++++-------- .../com/spertus/jacquard/PmdGraderTest.java | 4 +- .../java/com/spertus/jacquard/TargetTest.java | 63 +++++----------- 3 files changed, 60 insertions(+), 78 deletions(-) diff --git a/src/main/java/com/spertus/jacquard/common/Target.java b/src/main/java/com/spertus/jacquard/common/Target.java index 79fa4f1..236c95e 100644 --- a/src/main/java/com/spertus/jacquard/common/Target.java +++ b/src/main/java/com/spertus/jacquard/common/Target.java @@ -3,12 +3,14 @@ import com.spertus.jacquard.exceptions.ClientException; import java.io.File; +import java.io.IOException; import java.nio.file.*; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; /** - * The target of a {@link Grader}, such as a file or a directory. + * The target of a {@link Grader}, which must be a file. */ public final class Target { private static final String SUBMISSION_PATH_TEMPLATE = @@ -21,33 +23,35 @@ public final class Target { private final Path path; private Target(final Path path) { + if (path.toFile().isDirectory()) { + throw new ClientException("The path argument must be to a file, not a directory."); + } this.path = path; } /** - * Creates a target from a path, which could be to a file or directory. + * Creates a target from a path, which must be to a single file. * * @param path the path * @return the target + * @throws ClientException if the path is to a directory rather than a file */ public static Target fromPath(final Path path) { return new Target(path); } /** - * Creates a target from a relative path string. It does not matter whether + * Creates a target from a relative path string to a file. It does not matter whether * forward slashes or backslashes are used as separators. * - * @param s a relative path string + * @param s a relative path string to a file * @return the target - * - * @deprecated Call {@link #fromClass(Class)} instead. + * @throws ClientException if the path is to a directory rather than a file */ - @Deprecated() public static Target fromPathString(final String s) { // https://stackoverflow.com/a/40163941/631051 - final Path absPath = FileSystems.getDefault().getPath(s).normalize().toAbsolutePath(); - return new Target(absPath); + final Path path = FileSystems.getDefault().getPath(s).normalize().toAbsolutePath(); + return fromPath(path); } /** @@ -75,10 +79,10 @@ public static Target fromClass(Class targetClass) { * @param dir a relative directory string (ending with / or * \) * @param files the names of the files in the directory - * @return the target + * @return the targets * @throws ClientException if dir does not end with a path separator */ - private static List fromPathStrings(final String dir, final String... files) { + public static List fromPathStrings(final String dir, final String... files) { if (!dir.endsWith("/") && !dir.endsWith("\\")) { throw new ClientException("dir must end with a path separator (/ or \\)"); } @@ -87,6 +91,28 @@ private static List fromPathStrings(final String dir, final String... fi .collect(Collectors.toList()); } + /** + * Creates targets from all the files in the specified directory. + * + * @param dir a relative directory string + * @return the targets + * @throws ClientException if dir is not a directory or is not accessible + */ + public static List fromDirectory(final String dir) { + Path path = Paths.get(dir); + if (!path.toFile().isDirectory()) { + throw new ClientException("Argument to fromDirectory() must be a directory."); + } + try (Stream paths = Files.walk(path)) { + return paths + .filter(Files::isRegularFile) + .map(file -> fromPath(file.toAbsolutePath())) + .collect(Collectors.toList()); + } catch (IOException e) { + throw new ClientException("Unable to access directory " + dir); + } + } + /** * Gets the string representation of this target's absolute path. * @@ -115,40 +141,23 @@ public File toFile() { } /** - * Gets this target's directory. This is the target itself if it is a - * directory; otherwise, it is the parent directory of the file. + * Gets this target's directory. * * @return the directory */ public Path toDirectory() { final File file = toFile(); if (file.isDirectory()) { - return file.toPath(); + throw new RuntimeException("It should not be possible to have a Target that is a directory."); } else { return file.getParentFile().toPath(); } } -// /** -// * Parses this target, if it is a file. -// * -// * @param autograder autograder (for language level) -// * @return the parsed file -// * @throws ClientException if this target is a directory -// */ -// public CompilationUnit toCompilationUnit(Autograder autograder) { -// if (toFile().isDirectory()) { -// throw new ClientException("Cannot parse directory " + toPathString()); -// } -// return Parser.parse(autograder.getJavaLevel(), toFile()); -// } - @Override public boolean equals(final Object o) { if (o instanceof Target other) { - return this.toPath().equals(other.toPath()) && - this.toFile().equals(other.toFile()) && - this.toDirectory().equals(other.toDirectory()); + return this.path.equals(other.path); } return false; } diff --git a/src/test/java/com/spertus/jacquard/PmdGraderTest.java b/src/test/java/com/spertus/jacquard/PmdGraderTest.java index 37ca057..1af8467 100644 --- a/src/test/java/com/spertus/jacquard/PmdGraderTest.java +++ b/src/test/java/com/spertus/jacquard/PmdGraderTest.java @@ -109,8 +109,8 @@ public void testDirectory() { MAX_PENALTY, "category/java/documentation.xml", "category/java/codestyle.xml"); - Target target = Target.fromPathString("src/test/resources/good/"); - List results = pmdGrader.grade(target); // lots of errors + List targets = Target.fromDirectory("src/test/resources/good/"); + List results = pmdGrader.grade(targets); // lots of errors TestUtilities.assertResultsMatch(results, 1, 0, MAX_PENALTY); } diff --git a/src/test/java/com/spertus/jacquard/TargetTest.java b/src/test/java/com/spertus/jacquard/TargetTest.java index dc0e14d..6cf2626 100644 --- a/src/test/java/com/spertus/jacquard/TargetTest.java +++ b/src/test/java/com/spertus/jacquard/TargetTest.java @@ -6,6 +6,7 @@ import java.net.URISyntaxException; import java.nio.file.*; +import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -59,49 +60,21 @@ public void testToDirectoryForResource() { assertEquals(Paths.get(GOOD_RESOURCES_SUBDIR).toAbsolutePath(), mobTarget.toDirectory()); } -// @Test -// public void testToClassName() { -// assertEquals("Mob", mobTarget.toClassName()); -// } -// -// @Test -// public void testToClassNameThrowsExceptionForNonJava() { -// assertThrows(ClientException.class, -// () -> TestUtilities.getTargetFromResource("invalid/NotJava.txt").toClassName()); -// } -// -// @Test -// public void testToClassNameThrowsExceptionForDirectory() { -// assertThrows(ClientException.class, -// () -> Target.fromPathString(".").toClassName()); -// } -// -// @Test -// public void testToClassNameWorksForUnparseable() throws URISyntaxException { -// assertEquals("Unparseable", TestUtilities.getTargetFromResource("invalid/Unparseable.java").toClassName()); -// } -// -// @Test -// public void testToPackageName() { -// assertEquals("student", mobTarget.toPackageName()); -// } -// -// @Test -// public void testToPackageNameThrowsExceptionForNonJava() { -// assertThrows(ClientException.class, -// () -> TestUtilities.getTargetFromResource("invalid/NotJava.txt").toPackageName()); -// } -// -// @Test -// public void testToPackageNameThrowsExceptionForDirectory() { -// assertThrows(ClientException.class, -// () -> Target.fromPathString(".").toPackageName()); -// } -// -// @Test -// public void testToPackageNameThrowsExceptionForUnparseable() { -// assertThrows(ClientException.class, -// () -> TestUtilities.getTargetFromResource("invalid/Unparseable.java").toPackageName()); -// } + @Test + public void testFromDirectoryReturnsAllFiles() { + List targets = Target.fromDirectory("src/test/resources/good/"); + assertEquals(12, targets.size()); + } -} + @Test + public void testFromDirectoryRejectsFilePath() { + assertThrows(ClientException.class, + () -> Target.fromDirectory("src/test/resources/good/BadFormatting.java")); + } + + @Test + public void testFromDirectoryRejectsBadPath() { + assertThrows(ClientException.class, + () -> Target.fromDirectory("src/test/resources/nosuchdir")); + } +} \ No newline at end of file