Skip to content

Commit dbd4172

Browse files
Fix new failure in run.javac comparison from verifyClassFile() (eclipse-jdt#3619)
+ systematic handling of directories in AbstractModuleCompilationTests - no more ad-hoc use of 'javac' path segment - no longer pass 'output' parameter from individual tests + generally let ecj compile from 'src' to 'bin' + generally let javac compile from 'src' to 'javac' + when walking output files don't delete (for later inspection) + map ecj-output paths to expected javac-output paths - soften output when javac creates fewer classfiles in negative tests + support verifying classfiles from both compilers PR eclipse-jdt#3619
1 parent 7412090 commit dbd4172

File tree

4 files changed

+203
-215
lines changed

4 files changed

+203
-215
lines changed

org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractModuleCompilationTest.java

+123-100
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024 GK Software SE, and others.
2+
* Copyright (c) 2025 GK Software SE, and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -21,7 +21,6 @@
2121
import java.io.File;
2222
import java.io.FileWriter;
2323
import java.io.IOException;
24-
import java.nio.file.DirectoryNotEmptyException;
2524
import java.nio.file.FileVisitResult;
2625
import java.nio.file.Files;
2726
import java.nio.file.Path;
@@ -31,7 +30,9 @@
3130
import java.util.HashSet;
3231
import java.util.List;
3332
import java.util.Set;
33+
import java.util.stream.Collectors;
3434
import junit.framework.AssertionFailedError;
35+
import org.eclipse.jdt.core.util.ClassFormatException;
3536
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
3637

3738
public abstract class AbstractModuleCompilationTest extends AbstractBatchCompilerTest {
@@ -45,7 +46,7 @@ public AbstractModuleCompilationTest(String name) {
4546

4647
class Runner extends AbstractRegressionTest.Runner {
4748
StringBuilder commandLine = new StringBuilder();
48-
String outputDir = OUTPUT_DIR + File.separator + "javac";
49+
String outputDir = OUTPUT_DIR;
4950
List<String> fileNames = new ArrayList<>();
5051
/** will replace any -8, -9 ... option for javac */
5152
String javacVersionOptions;
@@ -72,11 +73,22 @@ Set<String> runConformModuleTest() {
7273
String javacCommandLine = adjustForJavac(commandLineString, this.javacVersionOptions);
7374
return AbstractModuleCompilationTest.this.runConformModuleTest(this.testFiles, commandLineString,
7475
this.expectedOutputString, this.expectedErrorString,
75-
this.shouldFlushOutputDirectory, this.outputDir,
76-
this.javacTestOptions, javacCommandLine);
76+
this.shouldFlushOutputDirectory, this.javacTestOptions,
77+
javacCommandLine);
7778
}
7879
}
7980

81+
protected String getSourceDir() {
82+
return OUTPUT_DIR + File.separatorChar + "src";
83+
}
84+
85+
protected String getEcjOutputDir() {
86+
return OUTPUT_DIR + File.separatorChar + "bin";
87+
}
88+
protected String getJavacOutputDir() {
89+
return OUTPUT_DIR + File.separatorChar + "javac";
90+
}
91+
8092
protected void writeFileCollecting(List<String> collectedFiles, String directoryName, String fileName, String source) {
8193
writeFile(directoryName, fileName, source);
8294
collectedFiles.add(directoryName+File.separator+fileName);
@@ -104,44 +116,47 @@ protected void writeFile(String directoryName, String fileName, String source) {
104116

105117
protected void runConformModuleTest(List<String> testFileNames, StringBuilder commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString) {
106118
runConformModuleTest(testFileNames, commandLine,
107-
expectedFailureOutOutputString, expectedFailureErrOutputString, OUTPUT_DIR + File.separator + "javac");
108-
}
109-
110-
protected void runConformModuleTest(List<String> testFileNames, StringBuilder commandLine,
111-
String expectedFailureOutOutputString, String expectedFailureErrOutputString,
112-
String output) {
113-
runConformModuleTest(testFileNames, commandLine,
114-
expectedFailureOutOutputString, expectedFailureErrOutputString, output,
115-
JavacTestOptions.DEFAULT);
119+
expectedFailureOutOutputString, expectedFailureErrOutputString, JavacTestOptions.DEFAULT);
116120
}
117121
protected void runConformModuleTest(List<String> testFileNames, StringBuilder commandLine,
118122
String expectedFailureOutOutputString, String expectedFailureErrOutputString,
119-
String output, JavacTestOptions javacTestOptions) {
123+
JavacTestOptions javacTestOptions) {
120124
for (String file : testFileNames)
121125
commandLine.append(" \"").append(file).append("\"");
122126
runConformModuleTest(new String[0], commandLine.toString(),
123127
expectedFailureOutOutputString, expectedFailureErrOutputString, false,
124-
output, javacTestOptions, null);
128+
javacTestOptions, null);
125129
}
126130

127131
protected Set<String> runConformModuleTest(String[] testFiles, String commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, boolean shouldFlushOutputDirectory) {
128132
return runConformModuleTest(testFiles, commandLine, expectedFailureErrOutputString, expectedFailureErrOutputString,
129-
shouldFlushOutputDirectory, OUTPUT_DIR, JavacTestOptions.DEFAULT, null);
133+
shouldFlushOutputDirectory, JavacTestOptions.DEFAULT, null);
130134
}
131135

132-
protected Set<String> runConformModuleTest(String[] testFiles, String commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, boolean shouldFlushOutputDirectory, String output,
133-
JavacTestOptions options, String javacCommandLine) {
134-
runConformTest(testFiles, commandLine, expectedFailureOutOutputString, expectedFailureErrOutputString, shouldFlushOutputDirectory);
136+
protected Set<String> runConformModuleTest(String[] testFiles, String commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, boolean shouldFlushOutputDirectory, JavacTestOptions options,
137+
String javacCommandLine) {
138+
String ecjOutput = getEcjOutputDir();
139+
File ecjOutFile = new File(ecjOutput);
140+
if (!ecjOutFile.exists()) {
141+
ecjOutFile.mkdir();
142+
}
143+
String ecjCommandLine = commandLine.contains("-d ")
144+
? commandLine
145+
: " -d " + ecjOutput + ' ' + commandLine;
146+
runConformTest(testFiles, ecjCommandLine, expectedFailureOutOutputString, expectedFailureErrOutputString, shouldFlushOutputDirectory);
135147
if (shouldRunJavac()) {
136-
File outputDir = new File(output);
137148
final Set<String> outFiles = new HashSet<>();
138-
walkOutFiles(output, outFiles, true);
149+
walkOutFiles(ecjOutput, outFiles, true);
150+
151+
String javacOutput = getJavacOutputDir();
152+
File javacOutputDir = new File(javacOutput);
153+
139154
String[] testFileNames = new String[testFiles.length/2];
140155
for (int i = 0; i < testFileNames.length; i++) {
141156
testFileNames[i] = testFiles[i*2];
142157
}
143158
if (javacCommandLine == null) {
144-
javacCommandLine = adjustForJavac(commandLine, null);
159+
javacCommandLine = " -d " + javacOutput + ' ' + adjustForJavac(commandLine, null);
145160
}
146161
for (JavacCompiler javacCompiler : javacCompilers) {
147162
if (javacCompiler.compliance < ClassFileConstants.JDK9)
@@ -153,7 +168,7 @@ protected Set<String> runConformModuleTest(String[] testFiles, String commandLin
153168
StringBuilder log = new StringBuilder();
154169
try {
155170
long compileResult = javacCompiler.compile(
156-
outputDir, /* directory */
171+
javacOutputDir, /* directory */
157172
javacCommandLine /* options */,
158173
testFileNames /* source file names */,
159174
log,
@@ -172,8 +187,8 @@ protected Set<String> runConformModuleTest(String[] testFiles, String commandLin
172187
e.printStackTrace();
173188
throw new AssertionFailedError(e.getMessage());
174189
}
175-
final Set<String> expectedFiles = new HashSet<>(outFiles);
176-
walkOutFiles(output, expectedFiles, false);
190+
final Set<String> expectedFiles = outFiles.stream().map(s -> s.replace(ecjOutput, javacOutput)).collect(Collectors.toSet());
191+
walkOutFiles(javacOutput, expectedFiles, false);
177192
for (String missingFile : expectedFiles)
178193
System.err.println("Missing output file from javac: "+missingFile);
179194
}
@@ -188,78 +203,88 @@ protected StringBuilder trimJavacLog(StringBuilder log) {
188203
}
189204

190205
protected void runNegativeModuleTest(List<String> testFileNames, StringBuilder commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, String javacErrorMatch) {
191-
runNegativeModuleTest(testFileNames, commandLine, expectedFailureOutOutputString,
192-
expectedFailureErrOutputString, javacErrorMatch, OUTPUT_DIR + File.separator + "javac");
193-
}
194-
195-
protected void runNegativeModuleTest(List<String> testFileNames, StringBuilder commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, String javacErrorMatch,
196-
String output) {
197-
runNegativeModuleTest(testFileNames, commandLine, expectedFailureOutOutputString, expectedFailureErrOutputString,
198-
javacErrorMatch, output, JavacTestOptions.DEFAULT);
199-
}
206+
runNegativeModuleTest(testFileNames, commandLine, expectedFailureOutOutputString, expectedFailureErrOutputString,
207+
javacErrorMatch, JavacTestOptions.DEFAULT);
208+
}
200209

201210
protected void runNegativeModuleTest(List<String> testFileNames, StringBuilder commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, String javacErrorMatch,
202-
String output, JavacTestOptions options) {
203-
for (String file : testFileNames)
204-
commandLine.append(" \"").append(file).append("\"");
205-
runNegativeModuleTest(new String[0], commandLine.toString(),
206-
expectedFailureOutOutputString, expectedFailureErrOutputString, false, javacErrorMatch, output,
207-
options);
208-
}
211+
JavacTestOptions options) {
212+
for (String file : testFileNames)
213+
commandLine.append(" \"").append(file).append("\"");
214+
runNegativeModuleTest(new String[0], commandLine.toString(),
215+
expectedFailureOutOutputString, expectedFailureErrOutputString, false, javacErrorMatch, options);
216+
}
209217

210218
protected void runNegativeModuleTest(String[] testFiles, String commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, boolean shouldFlushOutputDirectory,
211219
String javacErrorMatch) {
212-
runNegativeModuleTest(testFiles, commandLine, expectedFailureOutOutputString, expectedFailureErrOutputString,
213-
shouldFlushOutputDirectory, javacErrorMatch, OUTPUT_DIR, JavacTestOptions.DEFAULT);
214-
}
220+
String prefix = "src" + File.separatorChar;
221+
for (int i = 0; i + 1 < testFiles.length; i+=2) {
222+
testFiles[i] = prefix + testFiles[i];
223+
}
224+
runNegativeModuleTest(testFiles, commandLine, expectedFailureOutOutputString, expectedFailureErrOutputString,
225+
shouldFlushOutputDirectory, javacErrorMatch, JavacTestOptions.DEFAULT);
226+
}
215227

216228
void runNegativeModuleTest(String[] testFiles, String commandLine, String expectedFailureOutOutputString, String expectedFailureErrOutputString, boolean shouldFlushOutputDirectory, String javacErrorMatch,
217-
String output, JavacTestOptions options) {
218-
runNegativeTest(testFiles, commandLine, expectedFailureOutOutputString, expectedFailureErrOutputString, shouldFlushOutputDirectory);
219-
if (shouldRunJavac()) {
220-
String[] testFileNames = new String[testFiles.length/2];
221-
for (int i = 0; i < testFileNames.length; i++) {
222-
testFileNames[i] = testFiles[i*2];
223-
}
224-
File outputDir = new File(OUTPUT_DIR);
225-
final Set<String> outFiles = new HashSet<>();
226-
walkOutFiles(output, outFiles, true);
227-
for (JavacCompiler javacCompiler : javacCompilers) {
228-
if (javacCompiler.compliance < ClassFileConstants.JDK9)
229-
continue;
230-
JavacTestOptions.Excuse excuse = options.excuseFor(javacCompiler);
229+
JavacTestOptions options) {
230+
String ecjOutput = getEcjOutputDir();
231+
File ecjOutFile = new File(ecjOutput);
232+
if (!ecjOutFile.exists()) {
233+
ecjOutFile.mkdir();
234+
}
235+
String ecjCommandLine = commandLine.contains("-d ")
236+
? commandLine
237+
: " -d " + ecjOutput + ' ' + commandLine;
238+
runNegativeTest(testFiles, ecjCommandLine, expectedFailureOutOutputString, expectedFailureErrOutputString, shouldFlushOutputDirectory);
239+
if (shouldRunJavac()) {
240+
final Set<String> outFiles = new HashSet<>();
241+
walkOutFiles(ecjOutput, outFiles, true);
231242

232-
commandLine = adjustForJavac(commandLine, null);
233-
StringBuilder log = new StringBuilder();
234-
int mismatch = 0;
235-
try {
236-
long compileResult = javacCompiler.compile(
237-
outputDir, /* directory */
238-
commandLine /* options */,
239-
testFileNames /* source file names */,
240-
log);
241-
if (compileResult == 0) {
242-
mismatch = JavacTestOptions.MismatchType.EclipseErrorsJavacNone;
243-
javacErrorMatch = expectedFailureErrOutputString;
244-
System.err.println("Previous error was from "+testName());
245-
} else if (!log.toString().contains(javacErrorMatch)) {
246-
mismatch = JavacTestOptions.MismatchType.CompileErrorMismatch;
247-
System.err.println(testName()+": Error match " + javacErrorMatch + " not found in \n"+log.toString());
248-
}
249-
} catch (IOException | InterruptedException e) {
250-
e.printStackTrace();
251-
throw new AssertionFailedError(e.getMessage());
252-
}
253-
handleMismatch(javacCompiler, testName(), testFiles, javacErrorMatch,
254-
"", "", log, "", "",
255-
excuse, mismatch);
256-
final Set<String> expectedFiles = new HashSet<>(outFiles);
257-
walkOutFiles(output, expectedFiles, false);
258-
for (String missingFile : expectedFiles)
259-
System.err.println("Missing output file from javac: "+missingFile);
243+
String javacOutput = getJavacOutputDir();
244+
File outputDir = new File(javacOutput);
245+
246+
String[] testFileNames = new String[testFiles.length/2];
247+
for (int i = 0; i < testFileNames.length; i++) {
248+
testFileNames[i] = testFiles[i*2];
249+
}
250+
251+
for (JavacCompiler javacCompiler : javacCompilers) {
252+
if (javacCompiler.compliance < ClassFileConstants.JDK9)
253+
continue;
254+
JavacTestOptions.Excuse excuse = options.excuseFor(javacCompiler);
255+
256+
String javacCommandLine = " -d " + javacOutput + ' ' + adjustForJavac(commandLine, null);
257+
StringBuilder log = new StringBuilder();
258+
int mismatch = 0;
259+
try {
260+
long compileResult = javacCompiler.compile(
261+
outputDir, /* directory */
262+
javacCommandLine /* options */,
263+
testFileNames /* source file names */,
264+
log,
265+
false);
266+
if (compileResult == 0) {
267+
mismatch = JavacTestOptions.MismatchType.EclipseErrorsJavacNone;
268+
javacErrorMatch = expectedFailureErrOutputString;
269+
System.err.println("Previous error was from "+testName());
270+
} else if (!log.toString().contains(javacErrorMatch)) {
271+
mismatch = JavacTestOptions.MismatchType.CompileErrorMismatch;
272+
System.err.println(testName()+": Error match " + javacErrorMatch + " not found in \n"+log.toString());
260273
}
274+
} catch (IOException | InterruptedException e) {
275+
e.printStackTrace();
276+
throw new AssertionFailedError(e.getMessage());
261277
}
278+
handleMismatch(javacCompiler, testName(), testFiles, javacErrorMatch,
279+
"", "", log, "", "",
280+
excuse, mismatch);
281+
final Set<String> expectedFiles = outFiles.stream().map(s -> s.replace(ecjOutput, javacOutput)).collect(Collectors.toSet());
282+
walkOutFiles(javacOutput, expectedFiles, false);
283+
for (String missingFile : expectedFiles)
284+
System.out.println("Missing output file from javac in negative test: "+missingFile);
262285
}
286+
}
287+
}
263288

264289
/**
265290
* @param commandLine command line arguments as used for ecj
@@ -329,21 +354,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
329354
if (!fileNames.remove(file.toString()))
330355
System.err.println("Unexpected output file from javac: "+file.toString());
331356
}
332-
Files.delete(file);
333357
}
334358
return FileVisitResult.CONTINUE;
335359
}
336-
@Override
337-
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
338-
if (!dir.toString().equals(outputLocation)) {
339-
try {
340-
Files.delete(dir);
341-
} catch (DirectoryNotEmptyException ex) {
342-
// expected
343-
}
344-
}
345-
return FileVisitResult.CONTINUE;
346-
}
347360
});
348361
} catch (IOException e) {
349362
e.printStackTrace();
@@ -358,5 +371,15 @@ protected void assertClassFile(String msg, String fileName, Set<String> classFil
358371
assertTrue(msg, (new File(fileName).exists()));
359372
}
360373
}
361-
374+
@Override
375+
protected void verifyClassFile(String expectedOutput, String classFileName, int mode) throws IOException, ClassFormatException {
376+
verifyClassFile(expectedOutput, classFileName, mode, false);
377+
}
378+
protected void verifyClassFile(String expectedOutput, String classFileName, int mode, boolean skipJavac)
379+
throws IOException, ClassFormatException {
380+
verifyClassFile(expectedOutput, null, getEcjOutputDir()+File.separatorChar+classFileName, mode);
381+
if (!skipJavac && shouldRunJavac()) {
382+
verifyClassFile(expectedOutput, null, getJavacOutputDir()+File.separatorChar+classFileName, mode);
383+
}
384+
}
362385
}

org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1510,7 +1510,9 @@ protected void checkDisassembledClassFile(String fileName, String className, Str
15101510

15111511
protected static void verifyClassFile(String expectedOutput, String unexpectedOutput, String classFileName, int mode)
15121512
throws IOException, ClassFormatException {
1513-
File f = new File(OUTPUT_DIR + File.separator + classFileName);
1513+
if (!classFileName.startsWith(OUTPUT_DIR))
1514+
classFileName = OUTPUT_DIR + File.separator + classFileName;
1515+
File f = new File(classFileName);
15141516
byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
15151517
ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
15161518
String result = disassembler.disassemble(classFileBytes, "\n", mode);

0 commit comments

Comments
 (0)