Skip to content

Commit

Permalink
Merge pull request #137 from jplag/104-fix-cli
Browse files Browse the repository at this point in the history
Fix CLI and add testing capabilities
  • Loading branch information
sebinside authored Jun 16, 2021
2 parents af1c2a7 + 45d11cd commit bc88178
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 44 deletions.
53 changes: 40 additions & 13 deletions jplag/src/main/java/jplag/CLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@

/**
* Command line interface class, allows using via command line.
*
* @see CLI#main(String[])
*/
public class CLI {

private static final String DESCRIPTION = "JPlag - Detecting Software Plagiarism";
private static final String PROGRAM_NAME = "jplag";

// TODO SH: Replace verbosity when integrating a real logging library
private static final String[] verbosityOptions = {"parser", "quiet", "long", "details"};
private static final String[] languageOptions = new String[] {"java_1_1", "java_1_2", "java_1_5", "java_1_5_dm", "java_1_7", "java_1_9",
"python_3", "c_cpp", "c_sharp", "char", "text", "scheme"};


private final ArgumentParser parser;

/**
* Main class for using JPlag via the CLI.
*
* @param args are the CLI arguments that will be passed to JPlag.
*/
public static void main(String[] args) {
Expand All @@ -53,21 +55,27 @@ public static void main(String[] args) {
*/
public CLI() {
parser = ArgumentParsers.newFor(PROGRAM_NAME).build().defaultHelp(true).description(DESCRIPTION);

// TODO SH: Fix code duplication of CLI arguments
parser.addArgument("rootDir").help("The root-directory that contains all submissions");
parser.addArgument("-l").choices(languageOptions).setDefault("java_1_9").help("Select the language to parse the submissions");
parser.addArgument("-l")
.choices(LanguageOption.getAllDisplayNames())
.setDefault(LanguageOption.getDefault().getDisplayName())
.help("Select the language to parse the submissions");
parser.addArgument("-bc").help("Name of the directory which contains the base code (common framework)");
parser.addArgument("-v").choices(verbosityOptions).setDefault("quiet").help("Verbosity");
parser.addArgument("-d").help("(Debug) parser. Non-parsable files will be stored").action(storeTrue());
parser.addArgument("-S").help("Look in directories <root-dir>/*/<dir> for programs");
parser.addArgument("-p").help("comma-separated list of all filename suffixes that are included");
parser.addArgument("-x").help("All files named in <file> will be ignored");
parser.addArgument("-x").help("All files named in this file will be ignored in the comparison (line-separated list)");
parser.addArgument("-t").help("Tune the sensitivity of the comparison. A smaller <n> increases the sensitivity");
parser.addArgument("-s").help("Similarity Threshold: all matches above this threshold will be saved");
parser.addArgument("-r").setDefault("result").help("Name of directory in which the web pages will be stored");
parser.addArgument("-m").setDefault(0f).help("Match similarity Threshold [0-100]: all matches above this threshold will be saved");
parser.addArgument("-r").setDefault("result").help("Name of directory in which the comparison results will be stored");
}

/**
* Parses an array of argument strings.
*
* @param args is the array to parse.
* @return the parsed arguments in a {@link Namespace} format.
*/
Expand All @@ -83,27 +91,46 @@ public Namespace parseArguments(String[] args) {

/**
* Builds a options instance from parsed arguments.
*
* @param namespace encapsulates the parsed arguments in a {@link Namespace} format.
* @return the newly built options.F
*/
public JPlagOptions buildOptionsFromArguments(Namespace namespace) {
String fileSuffixString = namespace.getString("p");
String[] fileSuffixes = new String[] {};
String[] fileSuffixes = new String[]{};
if (fileSuffixString != null) {
fileSuffixes = fileSuffixString.replaceAll("\\s+", "").split(",");
}
LanguageOption language = LanguageOption.fromOption(namespace.getString("l"));
LanguageOption language = LanguageOption.fromDisplayName(namespace.getString("l"));
Verbosity verbosity = Verbosity.fromOption(namespace.getString("v"));

JPlagOptions options = new JPlagOptions(namespace.getString("rootDir"), language);
options.setBaseCodeSubmissionName("base-code");
options.setBaseCodeSubmissionName(namespace.getString("bc"));
options.setVerbosity(verbosity);
options.setDebugParser(namespace.getBoolean("d"));
options.setSubdirectoryName(namespace.getString("S"));
options.setFileSuffixes(fileSuffixes);
options.setExclusionFileName(namespace.getString("x"));
options.setMinTokenMatch(namespace.getInt("t"));
options.setSimilarityThreshold(namespace.getFloat("s"));

String minTokenMatch = namespace.getString("t");
if (minTokenMatch != null) {
try {
options.setMinTokenMatch(Integer.parseInt(minTokenMatch));
} catch (NumberFormatException e) {
System.out.println("Illegal comparison sensitivity. Ignoring input and taking language default value.");
}
}

String similarityThreshold = namespace.getString("m");
if (similarityThreshold != null) {
try {
options.setSimilarityThreshold(Float.parseFloat(similarityThreshold));
} catch (NumberFormatException e) {
System.out.println("Illegal similarity threshold. Taking 0 as default value.");
options.setSimilarityThreshold(0);
}
}

return options;
}
}
6 changes: 4 additions & 2 deletions jplag/src/main/java/jplag/JPlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,10 @@ protected JPlagOptions getOptions() {
*/
public boolean hasValidSuffix(File file) {
String[] validSuffixes = options.getFileSuffixes();

// This is the case if either the language frontends or the CLI did not set the valid suffixes array in options
if (validSuffixes == null || validSuffixes.length == 0) {
return true; // TODO TS: Why does this return true if the valid suffixes are not set?
return true;
}
return Arrays.stream(validSuffixes).anyMatch(suffix -> file.getName().endsWith(suffix));
}
Expand Down Expand Up @@ -380,7 +382,7 @@ private void parseBaseCodeSubmission(Submission subm) throws ExitException {
/**
* Parse all given submissions.
*/
private void parseSubmissions(Vector<Submission> submissions) throws ExitException {
private void parseSubmissions(Vector<Submission> submissions) {
if (submissions == null) {
System.out.println("Nothing to parse!");
return;
Expand Down
67 changes: 38 additions & 29 deletions jplag/src/main/java/jplag/options/LanguageOption.java
Original file line number Diff line number Diff line change
@@ -1,47 +1,56 @@
package jplag.options;

import jplag.java19.Language;

import java.util.Arrays;

/**
* The available languages.
*/
public enum LanguageOption {
JAVA_1_1("jplag.javax.Language"),
JAVA_1_2("jplag.java.Language"),
JAVA_1_5("jplag.java15.Language"),
JAVA_1_5_DM("jplag.java15.LanguageWithDelimitedMethods"),
JAVA_1_7("jplag.java17.Language"),
JAVA_1_9("jplag.java19.Language"),
PYTHON_3("jplag.python3.Language"),
C_CPP("jplag.cpp.Language"),
C_SHARP("jplag.csharp.Language"),
CHAR("jplag.chars.Language"),
TEXT("jplag.text.Language"),
SCHEME("jplag.scheme.Language");
JAVA_1_1("java1", "jplag.javax.Language"),
JAVA_1_2("java2", "jplag.java.Language"),
JAVA_1_5("java5", "jplag.java15.Language"),
JAVA_1_5_DM("java5dm", "jplag.java15.LanguageWithDelimitedMethods"),
JAVA_1_7("java7", "jplag.java17.Language"),
JAVA_1_9("java9", "jplag.java19.Language"),
PYTHON_3("python3", "jplag.python3.Language"),
C_CPP("cpp", "jplag.cpp.Language"),
C_SHARP("csharp", "jplag.csharp.Language"),
CHAR("char", "jplag.chars.Language"),
TEXT("text", "jplag.text.Language"),
SCHEME("scheme", "jplag.scheme.Language");

private final String classPath;
private final String displayName;

LanguageOption(String classPath) {
LanguageOption(String displayName, String classPath) {
this.displayName = displayName;
this.classPath = classPath;
}

public String getClassPath() {
return this.classPath;
}

public static LanguageOption fromOption(String optionName) {
switch(optionName) {
case "java_1_1": return JAVA_1_1;
case "java_1_2": return JAVA_1_2;
case "java_1_5": return JAVA_1_5;
case "java_1_5_dm": return JAVA_1_5_DM;
case "java_1_7": return JAVA_1_7;
case "java_1_9": return JAVA_1_9;
case "python_3": return PYTHON_3;
case "c_cpp": return C_CPP;
case "c_sharp": return C_SHARP;
case "char": return CHAR;
case "text": return TEXT;
case "scheme": return SCHEME;
default: return JAVA_1_9;
}
public String getDisplayName() {
return this.displayName;
}

public static LanguageOption fromDisplayName(String displayName) {
return Arrays.stream(LanguageOption.values())
.filter(languageOption -> languageOption.displayName.equals(displayName))
.findFirst()
.orElse(getDefault());
}

public static String[] getAllDisplayNames() {
return Arrays.stream(LanguageOption.values())
.map(languageOption -> languageOption.displayName)
.toArray(String[]::new);
}

public static LanguageOption getDefault() {
return LanguageOption.JAVA_1_9;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public JPlagResult compareSubmissions(Vector<Submission> submissions, Submission
continue;
}
comparison = greedyStringTiling.compare(first, second);

// TODO SH: Why does this differ from the results shown in the result web page?
System.out.println("Comparing " + first.name + "-" + second.name + ": " + comparison.percent());
if (baseCodeSubmission != null) {
comparison.bcMatchesA = baseCodeMatches.get(comparison.firstSubmission.name);
Expand Down
19 changes: 19 additions & 0 deletions jplag/src/test/java/jplag/NormalComparisonTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package jplag;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class NormalComparisonTests extends TestBase {

@Test
public void testSimpleDuplicate() throws ExitException {
JPlagResult result = runJPlagWithDefaultOptions("SimpleDuplicate");

assertEquals(2, result.getNumberOfSubmissions());
assertEquals(1, result.getComparisons().size());
assertEquals(1, result.getComparisons().get(0).matches.size());
assertEquals(1, result.getSimilarityDistribution()[6]);
}

}
17 changes: 17 additions & 0 deletions jplag/src/test/java/jplag/TestBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package jplag;

import jplag.options.JPlagOptions;
import jplag.options.LanguageOption;

public abstract class TestBase {

protected JPlagResult runJPlagWithDefaultOptions(String testSampleName) throws ExitException {
JPlagOptions options = new JPlagOptions(
String.format("src/test/resources/samples/%s", testSampleName),
LanguageOption.JAVA_1_9);

JPlag jplag = new JPlag(options);
return jplag.run();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
public class SimpleDuplicate {

public static void main(String[] args) {
System.out.println("Hello World!");

for(int i = 0; i < 10; i++) {
System.out.println("Number is " + i);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
public class SimpleDuplicate {

public static void main(String[] args) {
System.out.println("Hello Plagiarism!");

int max = 10;
for(int j = 0; j < max; j++) {
System.out.println("Number is " + j);
}
}

}

0 comments on commit bc88178

Please sign in to comment.