-
Notifications
You must be signed in to change notification settings - Fork 354
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1007 from plastic-karma/issue_675
allowing markers in jvm argument to preserve commas
- Loading branch information
Showing
3 changed files
with
155 additions
and
2 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
...mmand-line/src/main/java/org/pitest/mutationtest/commandline/CommaAwareArgsProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package org.pitest.mutationtest.commandline; | ||
|
||
import joptsimple.OptionSet; | ||
import joptsimple.OptionSpec; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* JVM args preprocessor to allow single arguments with commas. | ||
* The processor will first replace all commas with '@' if the comma is within a region of the argument marked by { and }. | ||
* The processor will then split up the arguments by commas that are outside the markers. | ||
* As a final step the '@' are replaced with commas again. | ||
*/ | ||
public class CommaAwareArgsProcessor { | ||
|
||
private static final char REGION_BEGIN = '{'; | ||
private static final char REGION_END = '}'; | ||
private final OptionSpec<String> optionsSpec; | ||
|
||
public CommaAwareArgsProcessor(OptionSpec<String> args) { | ||
this.optionsSpec = args; | ||
} | ||
|
||
public List<String> values(OptionSet userArgs) { | ||
final String commandLineOption = optionsSpec.value(userArgs); | ||
if (commandLineOption == null) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
Set<Integer> modifiedIndices = new HashSet<>(); | ||
String preprocessedOptions = replaceCommas(commandLineOption, modifiedIndices); | ||
|
||
String[] arguments = preprocessedOptions.split(","); | ||
return postProcess(modifiedIndices, arguments); | ||
} | ||
|
||
/** | ||
* Put commas back and delete region marker. | ||
*/ | ||
private List<String> postProcess(Set<Integer> modifiedIndices, String[] arguments) { | ||
List<String> newArguments = new ArrayList<>(); | ||
int base = 0; | ||
for (String argument : arguments) { | ||
newArguments.add(buildNewArgument(modifiedIndices, base, argument).toString()); | ||
base += argument.length() + 1; | ||
} | ||
return newArguments; | ||
} | ||
|
||
private StringBuilder buildNewArgument(Set<Integer> modifiedIndices, int base, String argument) { | ||
StringBuilder newArgument = new StringBuilder(); | ||
for (int j = 0; j < argument.length(); j++) { | ||
char current = argument.charAt(j); | ||
|
||
// Only remove region markers, if commas have been replaced. Otherwise treat them as part of the argument. | ||
if (!modifiedIndices.isEmpty() && (current == REGION_BEGIN || current == REGION_END)) { | ||
continue; | ||
} | ||
if (current == '@' && modifiedIndices.contains(j + base)) { | ||
newArgument.append(','); | ||
} else { | ||
newArgument.append(current); | ||
} | ||
} | ||
return newArgument; | ||
} | ||
|
||
private String replaceCommas(String single, Set<Integer> modifiedIndices) { | ||
StringBuilder newString = new StringBuilder(); | ||
boolean inSpecialRegion = false; | ||
for (int i = 0; i < single.length(); i++) { | ||
char current = single.charAt(i); | ||
char tobeAdded = current; | ||
if (current == REGION_BEGIN && !inSpecialRegion) { | ||
inSpecialRegion = true; | ||
} else if (current == REGION_END && inSpecialRegion) { | ||
inSpecialRegion = false; | ||
} else if (inSpecialRegion && current == ',') { | ||
tobeAdded = '@'; | ||
modifiedIndices.add(i); | ||
} | ||
newString.append(tobeAdded); | ||
} | ||
return newString.toString(); | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
...d-line/src/test/java/org/pitest/mutationtest/commandline/CommaAwareArgsProcessorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package org.pitest.mutationtest.commandline; | ||
|
||
import joptsimple.ArgumentAcceptingOptionSpec; | ||
import joptsimple.OptionParser; | ||
import joptsimple.OptionSet; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.junit.runners.Parameterized; | ||
import org.pitest.mutationtest.config.ConfigOption; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
@RunWith(Parameterized.class) | ||
public class CommaAwareArgsProcessorTest { | ||
|
||
@Parameterized.Parameters | ||
public static Collection<Object[]> data() { | ||
return Arrays.asList(new Object[][] { | ||
{ Arrays.asList("--unrelated", "a"), Collections.emptyList() }, | ||
{ Arrays.asList("--jvmArgs", "a"), Arrays.asList("a") }, | ||
{ Arrays.asList("--jvmArgs", "a,b,c,d"), Arrays.asList("a","b","c","d") }, | ||
{ Arrays.asList("--jvmArgs", "a;b,c;d"), Arrays.asList("a;b","c;d") }, | ||
{ Arrays.asList("--jvmArgs", "{a,b,c,d}"), Arrays.asList("a,b,c,d") }, | ||
{ Arrays.asList("--jvmArgs", "{a;b;c;d}"), Arrays.asList("{a;b;c;d}") }, // no separators so region markers will not be removed | ||
{ Arrays.asList("--jvmArgs", "{a,b},{c,d},{e,f}"), Arrays.asList("a,b","c,d","e,f") }, | ||
{ Arrays.asList("--jvmArgs", "{a,b@c,d}"), Arrays.asList("a,b@c,d") }, // pre-existing '@' will not be replaced with "," | ||
}); | ||
} | ||
|
||
private final List<String> input; | ||
private final List<String> expected; | ||
|
||
|
||
public CommaAwareArgsProcessorTest(List<String> input, List<String> expected) { | ||
this.input = input; | ||
this.expected = expected; | ||
} | ||
|
||
@Test | ||
public void parseArgs() { | ||
OptionParser optionParser = new OptionParser(); | ||
ArgumentAcceptingOptionSpec<String> args = optionParser | ||
.accepts(ConfigOption.CHILD_JVM.getParamName()) | ||
.withRequiredArg() | ||
.describedAs("jvm args for child JVM"); | ||
ArgumentAcceptingOptionSpec<String> unrelatedArgs = optionParser | ||
.accepts("unrelated") | ||
.withRequiredArg() | ||
.describedAs("unrelatedArgs"); | ||
|
||
final OptionSet userArgs = optionParser.parse(this.input.toArray(new String[0])); | ||
Assert.assertEquals(this.expected, new CommaAwareArgsProcessor(args).values(userArgs)); | ||
} | ||
|
||
} |