Skip to content

Commit

Permalink
8319046: Execute tests in source/class-file order in JavadocTester
Browse files Browse the repository at this point in the history
Reviewed-by: hannesw
  • Loading branch information
jonathan-gibbons committed Nov 1, 2023
1 parent 3660a90 commit c86592d
Showing 1 changed file with 68 additions and 7 deletions.
75 changes: 68 additions & 7 deletions test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.SoftReference;
Expand Down Expand Up @@ -59,8 +58,11 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.tools.StandardJavaFileManager;

//import jdk.lang.classfile.Classfile;


/**
* Test framework for running javadoc and performing tests on the resulting output.
Expand Down Expand Up @@ -292,16 +294,75 @@ public void runTests() throws Exception {
* @throws Exception if any errors occurred while executing a test method
*/
public void runTests(Function<Method, Object[]> f) throws Exception {
for (Method m : getClass().getDeclaredMethods()) {
Annotation a = m.getAnnotation(Test.class);
if (a != null) {
runTest(m, f);
out.println();
}
var methods = List.of(getClass().getDeclaredMethods()).stream()
.filter(m -> m.isAnnotationPresent(Test.class))
.collect(Collectors.toCollection(() -> new ArrayList<>()));
var methodOrderComparator = getMethodComparator();
if (methodOrderComparator != null) {
methods.sort(methodOrderComparator);
}
for (Method m : methods) {
runTest(m, f);
out.println();
}
printSummary();
}

// The following is for when the Classfile library is generally available.
// private Comparator<Method> getClassOrderMethodComparator(Class<?> c) {
// try {
// var url = c.getProtectionDomain().getCodeSource().getLocation();
// var path = Path.of(url.toURI()).resolve(c.getName().replace(".", "/") + ".class");
// var cf = Classfile.of().parse(path);
// var map = new HashMap<String, Integer>();
// var index = 0;
// for (var m : cf.methods()) {
// map.putIfAbsent(m.methodName().stringValue(), index++);
// }
// return Comparator.<Method>comparingInt(m -> map.getOrDefault(m.getName(), -1));
// } catch (URISyntaxException | IOException e) {
// throw new Error("Cannot sort methods: " + e, e);
// }
// }

/**
* {@return the comparator used to sort the default set of methods to be executed,
* or {@code null} if the methods should not be sorted }
*
* @implSpec This implementation returns a source-order comparator.
*/
public Comparator<Method> getMethodComparator() {
return getSourceOrderMethodComparator(getClass());
}

/**
* {@return the source-order method comparator for methods in the given class}
* @param c the class
*/
public static Comparator<Method> getSourceOrderMethodComparator(Class<?> c) {
var path = Path.of(testSrc)
.resolve(c.getName()
.replace(".", "/")
.replaceAll("\\$.*", "")
+ ".java");
try {
var src = Files.readString(path);
// Fuzzy match for test method declarations.
// It doesn't matter if there are false positives, as long as the true positives are in the correct order.
// It doesn't matter too much if there are false negatives: they'll just be executed first.
var isMethodDecl = Pattern.compile("public +void +(?<name>[A-Za-z][A-Za-z0-9_]*)\\(");
var matcher = isMethodDecl.matcher(src);
var map = new HashMap<String, Integer>();
var index = 0;
while (matcher.find()) {
map.putIfAbsent(matcher.group("name"), index++);
}
return Comparator.<Method>comparingInt(m -> map.getOrDefault(m.getName(), -1));
} catch (IOException e) {
throw new Error("Cannot sort methods: " + e, e);
}
}

/**
* Run the specified methods annotated with @Test, or all methods annotated
* with @Test if none are specified, followed by printSummary.
Expand Down

1 comment on commit c86592d

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.