Skip to content

Commit 072caa5

Browse files
authored
Merge pull request #1422 from hcoles/bug/arg_files
Handle args files in the argLine
2 parents 35e6f10 + cb4e169 commit 072caa5

File tree

6 files changed

+190
-5
lines changed

6 files changed

+190
-5
lines changed

pitest-entry/src/main/java/org/pitest/process/Java9Process.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.File;
44
import java.io.IOException;
5+
import java.io.UncheckedIOException;
56
import java.lang.management.ManagementFactory;
67
import java.lang.management.RuntimeMXBean;
78
import java.nio.file.Files;
@@ -72,12 +73,12 @@ public JavaProcess getProcess() {
7273
}
7374

7475
private ProcessBuilder createProcessBuilder(String javaProc,
75-
List<String> args, Class<?> mainClass, String programArgs,
76+
List<String> unsanitisedArgs, Class<?> mainClass, String programArgs,
7677
JavaAgent javaAgent, String classPath) {
77-
List<String> fileArgs = createLaunchArgs(javaAgent, args, classPath);
7878

79-
removeJacocoAgent(fileArgs);
79+
List<String> fileArgs = createLaunchArgs(javaAgent, unsanitisedArgs, classPath);
8080

81+
removeJacocoAgent(fileArgs);
8182

8283
// All arguments are passed via a temporary file, thereby avoiding command line length limits
8384
Path argsFile = CACHE.computeIfAbsent(javaAgent.getJarLocation(), j -> createArgsFile(fileArgs));
@@ -86,11 +87,21 @@ private ProcessBuilder createProcessBuilder(String javaProc,
8687
cmd.add(javaProc);
8788
addLaunchJavaAgentsAndEnvironmentVariables(cmd);
8889
cmd.add("@" + argsFile.toFile().getAbsolutePath());
90+
8991
cmd.add(mainClass.getName());
9092
cmd.add(programArgs);
9193

9294
return new ProcessBuilder(cmd);
9395
}
96+
97+
private List<String> removeArgFiles(List<String> args) {
98+
return args.stream()
99+
.map(String::trim)
100+
.filter(a -> !a.startsWith("@"))
101+
.collect(Collectors.toList());
102+
}
103+
104+
94105
private void removeJacocoAgent(List<String> cmd) {
95106
removeFromClassPath(cmd, line -> line.startsWith("-javaagent") && line.contains("jacoco"));
96107
}
@@ -105,18 +116,42 @@ private static void removeFromClassPath(List<String> cmd, Predicate<String> matc
105116

106117
private List<String> createLaunchArgs(JavaAgent agentJarLocator, List<String> args, String classPath) {
107118

119+
// remove other arg files from the command line
120+
List<String> argsWithoutArgFiles = removeArgFiles(args);
121+
108122
List<String> cmd = new ArrayList<>();
109123

110124
cmd.add("-classpath");
111125
cmd.add(classPath.replace(" ", "\" \""));
112126

113127
addPITJavaAgent(agentJarLocator, cmd);
128+
cmd.addAll(argsWithoutArgFiles);
129+
130+
// We could pass the existing argfiles through as is, however
131+
// they may be designed for the module pass. As we don't properly
132+
// support the module path yet, the best we can do is strip
133+
// add-modules lines out. Since we're already creating an args file
134+
// we can append the existing files onto it with filtering.
135+
List<String> existing = findArgsFiles(args).stream()
136+
.flatMap(f -> readFile(f).stream())
137+
.filter(l -> !l.trim().startsWith("--add-modules"))
138+
.collect(Collectors.toList());
139+
114140

115-
cmd.addAll(args);
141+
cmd.addAll(existing);
116142

117143
return cmd;
118144
}
119145

146+
private static List<String> readFile(String f) {
147+
try {
148+
return Files.readAllLines(Path.of(f));
149+
} catch (IOException e) {
150+
throw new UncheckedIOException(e);
151+
}
152+
}
153+
154+
120155
private Path createArgsFile(List<String> cmd) {
121156
try {
122157
// All files should be deleted on process exit, although some garbage may be left
@@ -154,5 +189,11 @@ private static Predicate<String> isJavaAgentParam() {
154189
return a -> a.toLowerCase().startsWith("-javaagent");
155190
}
156191

157-
192+
private List<String> findArgsFiles(List<String> args) {
193+
return args.stream()
194+
.map(String::trim)
195+
.filter(a -> a.startsWith("@"))
196+
.map(a -> a.substring(1))
197+
.collect(Collectors.toList());
198+
}
158199
}

pitest-maven-verification/src/test/java/org/pitest/PitMojoIT.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ public void shouldHandleSpacesInProjectPath() throws Exception {
115115
}
116116

117117

118+
@Test
119+
public void shouldRunWhenModulesAddedViaArgsFile() throws Exception {
120+
File testDir = prepare("/pit-adds-modules-via-file");
121+
verifier.executeGoal("test-compile");
122+
verifier.executeGoal("org.pitest:pitest-maven:mutationCoverage");
123+
124+
String actual = readResults(testDir);
125+
assertThat(actual)
126+
.contains(
127+
"<mutation detected='false'");
128+
}
129+
118130
@Test
119131
public void shouldExcludeSpecifiedJUnitCategories() throws Exception {
120132
File testDir = prepare("/pit-junit-categories");
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### in-module testing ###
2+
--add-modules does.not.exist.so.will.cause.error.if.not.filtered
3+
### java.base ###
4+
--add-opens java.base/java.lang=ALL-UNNAMED
5+
--add-opens java.base/java.math=ALL-UNNAMED
6+
--add-opens java.base/java.util=ALL-UNNAMED
7+
--add-opens java.base/sun.nio.fs=ALL-UNNAME
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>org.example</groupId>
5+
<artifactId>module-file</artifactId>
6+
<packaging>jar</packaging>
7+
<version>1.0-SNAPSHOT</version>
8+
<name>module-file</name>
9+
<dependencies>
10+
<dependency>
11+
<groupId>junit</groupId>
12+
<artifactId>junit</artifactId>
13+
<version>${junit.version}</version>
14+
</dependency>
15+
</dependencies>
16+
<build>
17+
<plugins>
18+
<plugin>
19+
<groupId>org.apache.maven.plugins</groupId>
20+
<artifactId>maven-compiler-plugin</artifactId>
21+
<version>3.10.1</version>
22+
<configuration>
23+
<release>11</release>
24+
</configuration>
25+
</plugin>
26+
<plugin>
27+
<groupId>org.pitest</groupId>
28+
<artifactId>pitest-maven</artifactId>
29+
<version>${pit.version}</version>
30+
<configuration>
31+
<exportLineCoverage>true</exportLineCoverage>
32+
<features>+CLASSLIMIT(limit[1])</features>
33+
<timestampedReports>false</timestampedReports>
34+
<targetClasses><param>com.example*</param></targetClasses>
35+
<verbose>true</verbose>
36+
<outputFormats>
37+
<outputFormat>XML</outputFormat>
38+
</outputFormats>
39+
</configuration>
40+
</plugin>
41+
</plugins>
42+
</build>
43+
44+
45+
<properties>
46+
<junit.version>4.13.1</junit.version>
47+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
48+
<argLine>
49+
-Dfile.encoding=${project.build.sourceEncoding}
50+
-Dnet.bytebuddy.experimental=true
51+
@${project.basedir}/argFile
52+
</argLine>
53+
</properties>
54+
55+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.example;
2+
3+
public class CoveredByMultipleThreads {
4+
5+
public int lotsOfLinesOfCode(int i) {
6+
if ( i == 0 ) {
7+
return 1;
8+
}
9+
10+
if ( i == 2 ) {
11+
return 42;
12+
}
13+
14+
for ( int j = 0; j != 100; j++ ) {
15+
try {
16+
Thread.sleep(1);
17+
} catch (InterruptedException e) {
18+
e.printStackTrace();
19+
}
20+
}
21+
22+
return i;
23+
}
24+
25+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.example;
2+
3+
import java.util.Arrays;
4+
import java.util.Collection;
5+
6+
import org.junit.Test;
7+
import org.junit.runner.RunWith;
8+
import org.junit.runners.Parameterized;
9+
import org.junit.runners.Parameterized.Parameters;
10+
11+
@RunWith(value = Parameterized.class)
12+
public class MultiThreadedTest {
13+
14+
private final int i;
15+
16+
@Parameters
17+
public static Collection<Object[]> data() {
18+
Object[][] data = new Object[][] { { 1 }, { 2 }, { 3 }, { 4 }, { 5 } ,{ 6 }, { 7 }, { 8 } };
19+
return Arrays.asList(data);
20+
}
21+
22+
public MultiThreadedTest(int i) {
23+
this.i = i;
24+
}
25+
26+
@Test
27+
public void test() throws InterruptedException {
28+
Thread t = new Thread(aTest());
29+
t.start();
30+
t.join();
31+
}
32+
33+
34+
35+
private Runnable aTest() {
36+
return new Runnable() {
37+
public void run() {
38+
CoveredByMultipleThreads testee = new CoveredByMultipleThreads();
39+
testee.lotsOfLinesOfCode(i);
40+
}
41+
42+
};
43+
};
44+
45+
}

0 commit comments

Comments
 (0)