8178835: CTW Runner should check that all classes have been compiled

Reviewed-by: kvn
This commit is contained in:
Igor Ignatyev 2017-04-18 20:10:55 -07:00
parent 154b7f24cb
commit c3d400001c
9 changed files with 98 additions and 11 deletions

View File

@ -33,6 +33,6 @@
* @build sun.hotspot.WhiteBox * @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission * sun.hotspot.WhiteBox$WhiteBoxPermission
* @run driver/timeout=0 sun.hotspot.tools.ctw.CtwRunner modules * @run main/timeout=0 sun.hotspot.tools.ctw.CtwRunner modules
*/ */

View File

@ -66,6 +66,16 @@ public class ClassPathDirEntry extends PathHandler {
} }
} }
@Override
public long classCount() {
try {
return Files.walk(root, FileVisitOption.FOLLOW_LINKS).count();
} catch (IOException e) {
throw new Error("can not walk dir " + root + " : "
+ e.getMessage(), e);
}
}
private void processFile(Path file) { private void processFile(Path file) {
if (Utils.isClassFile(file.toString())) { if (Utils.isClassFile(file.toString())) {
processClass(pathToClassName(file)); processClass(pathToClassName(file));

View File

@ -69,7 +69,20 @@ public class ClassPathJarEntry extends PathHandler {
} }
} }
private void processJarEntry(JarEntry entry) { @Override
public long classCount() {
try (JarFile jarFile = new JarFile(root.toFile())) {
return jarFile.stream()
.map(JarEntry::getName)
.filter(Utils::isClassFile)
.count();
} catch (IOException e) {
throw new Error("can not open jar file " + root + " : "
+ e.getMessage() , e);
}
}
private void processJarEntry(JarEntry entry) {
String filename = entry.getName(); String filename = entry.getName();
if (Utils.isClassFile(filename)) { if (Utils.isClassFile(filename)) {
processClass(Utils.fileNameToClassName(filename)); processClass(Utils.fileNameToClassName(filename));

View File

@ -56,5 +56,18 @@ public class ClassPathJarInDirEntry extends PathHandler {
ioe.printStackTrace(); ioe.printStackTrace();
} }
} }
@Override
public long classCount() {
try {
return Files.list(root)
.filter(p -> p.getFileName().toString().endsWith(".jar"))
.map(p -> new ClassPathJarEntry(p, executor))
.mapToLong(ClassPathJarEntry::classCount).sum();
} catch (IOException e) {
throw new Error("can not walk dir " + root + " : "
+ e.getMessage(), e);
}
}
} }

View File

@ -64,4 +64,18 @@ public class ClassPathJimageEntry extends PathHandler {
ioe.printStackTrace(); ioe.printStackTrace();
} }
} }
@Override
public long classCount() {
try (ImageReader reader = ImageReader.open(root)) {
return Arrays.stream(reader.getEntryNames())
.filter(name -> name.endsWith(".class"))
.filter(name -> !name.endsWith("module-info.class"))
.map(Utils::fileNameToClassName)
.count();
} catch (IOException e) {
throw new Error("can not open jimage file " + root + " : "
+ e.getMessage() , e);
}
}
} }

View File

@ -45,8 +45,7 @@ public class ClassesListInFile extends PathHandler {
return; return;
} }
try { try {
try (BufferedReader reader = Files.newBufferedReader(root, try (BufferedReader reader = Files.newBufferedReader(root)) {
StandardCharsets.UTF_8)) {
String line; String line;
while (!isFinished() && ((line = reader.readLine()) != null)) { while (!isFinished() && ((line = reader.readLine()) != null)) {
processClass(line); processClass(line);
@ -56,4 +55,16 @@ public class ClassesListInFile extends PathHandler {
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override
public long classCount() {
try {
try (BufferedReader reader = Files.newBufferedReader(root)) {
return reader.lines().count();
}
} catch (IOException e) {
throw new Error("can not read list " + root + " : "
+ e.getMessage(), e);
}
}
} }

View File

@ -83,7 +83,7 @@ public class CompileTheWorld {
await(executor); await(executor);
} }
CompileTheWorld.OUT.printf("Done (%d classes, %d methods, %d ms)%n", CompileTheWorld.OUT.printf("Done (%d classes, %d methods, %d ms)%n",
PathHandler.getClassCount(), PathHandler.getProcessedClassCount(),
Compiler.getMethodCount(), Compiler.getMethodCount(),
System.currentTimeMillis() - start); System.currentTimeMillis() - start);
passed = true; passed = true;

View File

@ -23,6 +23,7 @@
package sun.hotspot.tools.ctw; package sun.hotspot.tools.ctw;
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils; import jdk.test.lib.Utils;
import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.util.Pair; import jdk.test.lib.util.Pair;
@ -34,6 +35,8 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -98,7 +101,10 @@ public class CtwRunner {
private void startCtwforAllClasses() { private void startCtwforAllClasses() {
long classStart = 0; long classStart = 0L;
long classCount = classCount();
Asserts.assertGreaterThan(classCount, 0L,
targetPath + " does not have any classes");
boolean done = false; boolean done = false;
while (!done) { while (!done) {
String[] cmd = cmd(classStart); String[] cmd = cmd(classStart);
@ -124,6 +130,16 @@ public class CtwRunner {
exitCode); exitCode);
Pair<String, Long> lastClass = getLastClass(out); Pair<String, Long> lastClass = getLastClass(out);
if (exitCode == 0) { if (exitCode == 0) {
long lastIndex = lastClass == null ? -1 : lastClass.second;
if (lastIndex != classCount) {
errors.add(new Error(phase + ": Unexpected zero exit code"
+ "before finishing all compilations."
+ " lastClass[" + lastIndex
+ "] != classCount[" + classCount + "]"));
} else {
System.out.println("Executed CTW for all " + classCount
+ " classes in " + targetPath);
}
done = true; done = true;
} else { } else {
if (lastClass == null) { if (lastClass == null) {
@ -145,6 +161,11 @@ public class CtwRunner {
} }
} }
private long classCount() {
return PathHandler.create(targetPath.toString(), Runnable::run)
.classCount();
}
private Pair<String, Long> getLastClass(Path errFile) { private Pair<String, Long> getLastClass(Path errFile) {
try (BufferedReader reader = Files.newBufferedReader(errFile)) { try (BufferedReader reader = Files.newBufferedReader(errFile)) {
String line = reader.lines() String line = reader.lines()
@ -167,7 +188,7 @@ public class CtwRunner {
private String[] cmd(long classStart) { private String[] cmd(long classStart) {
String phase = phaseName(classStart); String phase = phaseName(classStart);
return new String[]{ return new String[] {
"-Xbatch", "-Xbatch",
"-XX:-UseCounterDecay", "-XX:-UseCounterDecay",
"-XX:-ShowMessageBoxOnError", "-XX:-ShowMessageBoxOnError",

View File

@ -62,7 +62,7 @@ public abstract class PathHandler {
this.loader = ClassLoader.getSystemClassLoader(); this.loader = ClassLoader.getSystemClassLoader();
} }
/** /**
* Factory method. Construct concrete handler in depends from {@code path}. * Factory method. Construct concrete handler in depends from {@code path}.
* *
* @param path the path to process * @param path the path to process
@ -118,11 +118,16 @@ public abstract class PathHandler {
} }
/** /**
* Processes all classes in specified path. * Processes all classes in the specified path.
*/ */
public abstract void process(); public abstract void process();
/** /**
* @return count of all classes in the specified path.
*/
public abstract long classCount();
/**
* Sets class loader, that will be used to define class at * Sets class loader, that will be used to define class at
* {@link #processClass(String)}. * {@link #processClass(String)}.
* *
@ -168,7 +173,7 @@ public abstract class PathHandler {
/** /**
* @return count of processed classes * @return count of processed classes
*/ */
public static long getClassCount() { public static long getProcessedClassCount() {
long id = CLASS_COUNT.get(); long id = CLASS_COUNT.get();
if (id < Utils.COMPILE_THE_WORLD_START_AT) { if (id < Utils.COMPILE_THE_WORLD_START_AT) {
return 0; return 0;