From 8e3166c992abc5ca0324fdb21cbe3afd3b051ec5 Mon Sep 17 00:00:00 2001 From: "brian.mcnamara" Date: Thu, 8 Aug 2024 09:58:11 -0700 Subject: [PATCH] Allow JUnit5 runner to be extended --- .../junit5/ActualRunner.java | 125 ++++++++++-------- .../junit5/JUnit5Runner.java | 16 ++- 2 files changed, 82 insertions(+), 59 deletions(-) diff --git a/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/ActualRunner.java b/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/ActualRunner.java index a8c1c717..644532a9 100644 --- a/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/ActualRunner.java +++ b/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/ActualRunner.java @@ -22,9 +22,11 @@ import java.util.stream.Collectors; import org.junit.jupiter.engine.Constants; import org.junit.platform.engine.DiscoverySelector; +import org.junit.platform.engine.Filter; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherConstants; +import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TagFilter; import org.junit.platform.launcher.core.LauncherConfig; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; @@ -60,65 +62,12 @@ public boolean run(String testClassName) { .addPostDiscoveryFilters(TestSharding.makeShardFilter()) .build(); - final Class testClass; - try { - testClass = Class.forName(testClassName, false, getClass().getClassLoader()); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Failed to find testClass", e); - } - - // We only allow for one level of nesting at the moment - boolean enclosed = isRunWithEnclosed(testClass); - List classSelectors = - enclosed - ? new ArrayList<>() - : Arrays.stream(testClass.getDeclaredClasses()) - .filter(clazz -> Modifier.isStatic(clazz.getModifiers())) - .map(DiscoverySelectors::selectClass) - .collect(Collectors.toList()); - - classSelectors.add(DiscoverySelectors.selectClass(testClassName)); - - LauncherDiscoveryRequestBuilder request = - LauncherDiscoveryRequestBuilder.request() - .selectors(classSelectors) - .configurationParameter(LauncherConstants.CAPTURE_STDERR_PROPERTY_NAME, "true") - .configurationParameter(LauncherConstants.CAPTURE_STDOUT_PROPERTY_NAME, "true") - .configurationParameter( - Constants.EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME, "true"); - - String filter = System.getenv("TESTBRIDGE_TEST_ONLY"); - request.filters(new PatternFilter(filter)); - - String includeTags = System.getProperty("JUNIT5_INCLUDE_TAGS"); - if (includeTags != null && !includeTags.isEmpty()) { - request.filters(TagFilter.includeTags(includeTags.split(","))); - } - - String excludeTags = System.getProperty("JUNIT5_EXCLUDE_TAGS"); - if (excludeTags != null && !excludeTags.isEmpty()) { - request.filters(TagFilter.excludeTags(excludeTags.split(","))); - } - - List includeEngines = - System.getProperty("JUNIT5_INCLUDE_ENGINES") == null - ? null - : Arrays.asList(System.getProperty("JUNIT5_INCLUDE_ENGINES").split(",")); - List excludeEngines = - System.getProperty("JUNIT5_EXCLUDE_ENGINES") == null - ? null - : Arrays.asList(System.getProperty("JUNIT5_EXCLUDE_ENGINES").split(",")); - if (includeEngines != null) { - request.filters(includeEngines(includeEngines)); - } - if (excludeEngines != null) { - request.filters(excludeEngines(excludeEngines)); - } + LauncherDiscoveryRequest request = getRequest(testClassName); File exitFile = getExitFile(); Launcher launcher = LauncherFactory.create(config); - launcher.execute(request.build()); + launcher.execute(request); deleteExitFile(exitFile); @@ -130,6 +79,72 @@ public boolean run(String testClassName) { } } + protected LauncherDiscoveryRequest getRequest(String testClassName) { + final Class testClass; + try { + testClass = Class.forName(testClassName, false, getClass().getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Failed to find testClass", e); + } + + // We only allow for one level of nesting at the moment + boolean enclosed = isRunWithEnclosed(testClass); + List classSelectors = + enclosed + ? new ArrayList<>() + : Arrays.stream(testClass.getDeclaredClasses()) + .filter(clazz -> Modifier.isStatic(clazz.getModifiers())) + .map(DiscoverySelectors::selectClass) + .collect(Collectors.toList()); + + classSelectors.add(DiscoverySelectors.selectClass(testClassName)); + + LauncherDiscoveryRequestBuilder request = + LauncherDiscoveryRequestBuilder.request() + .selectors(classSelectors) + .configurationParameter(LauncherConstants.CAPTURE_STDERR_PROPERTY_NAME, "true") + .configurationParameter(LauncherConstants.CAPTURE_STDOUT_PROPERTY_NAME, "true") + .configurationParameter( + Constants.EXTENSIONS_AUTODETECTION_ENABLED_PROPERTY_NAME, "true") + .filters(getFilters().toArray(new Filter[0])); + + return request.build(); + } + + protected List> getFilters() { + List> filters = new ArrayList<>(); + + String filter = System.getenv("TESTBRIDGE_TEST_ONLY"); + filters.add(new PatternFilter(filter)); + + String includeTags = System.getProperty("JUNIT5_INCLUDE_TAGS"); + if (includeTags != null && !includeTags.isEmpty()) { + filters.add(TagFilter.includeTags(includeTags.split(","))); + } + + String excludeTags = System.getProperty("JUNIT5_EXCLUDE_TAGS"); + if (excludeTags != null && !excludeTags.isEmpty()) { + filters.add(TagFilter.excludeTags(excludeTags.split(","))); + } + + List includeEngines = + System.getProperty("JUNIT5_INCLUDE_ENGINES") == null + ? null + : Arrays.asList(System.getProperty("JUNIT5_INCLUDE_ENGINES").split(",")); + List excludeEngines = + System.getProperty("JUNIT5_EXCLUDE_ENGINES") == null + ? null + : Arrays.asList(System.getProperty("JUNIT5_EXCLUDE_ENGINES").split(",")); + if (includeEngines != null) { + filters.add(includeEngines(includeEngines)); + } + if (excludeEngines != null) { + filters.add(excludeEngines(excludeEngines)); + } + + return filters; + } + /** * Checks if the test class is annotation with `@RunWith(Enclosed.class)`. We deliberately avoid * using types here to avoid polluting the classpath with junit4 deps. diff --git a/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/JUnit5Runner.java b/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/JUnit5Runner.java index e7ce869b..8bcd4264 100644 --- a/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/JUnit5Runner.java +++ b/java/src/com/github/bazel_contrib/contrib_rules_jvm/junit5/JUnit5Runner.java @@ -19,6 +19,10 @@ public class JUnit5Runner { "com.github.bazel_contrib.contrib_rules_jvm.junit5.Java17SystemExitToggle"; public static void main(String[] args) { + new JUnit5Runner().run(); + } + + public void run() { String testSuite = System.getProperty("bazel.test_suite"); SystemExitToggle systemExitToggle = getSystemExitToggle(); @@ -33,9 +37,7 @@ public static void main(String[] args) { systemExitToggle.prevent(); try { - Constructor constructor = - Class.forName(JUNIT5_RUNNER_CLASS).asSubclass(RunsTest.class).getConstructor(); - RunsTest runsTest = constructor.newInstance(); + RunsTest runsTest = getRunner(); if (!runsTest.run(testSuite)) { exit(systemExitToggle, 2); } @@ -50,7 +52,13 @@ public static void main(String[] args) { exit(systemExitToggle, 0); } - private static SystemExitToggle getSystemExitToggle() { + protected RunsTest getRunner() throws ReflectiveOperationException { + Constructor constructor = + Class.forName(JUNIT5_RUNNER_CLASS).asSubclass(RunsTest.class).getConstructor(); + return constructor.newInstance(); + } + + protected SystemExitToggle getSystemExitToggle() { // In Java 8 and lower, the first part of the version is a 1. // In Java 9 and higher, the first part of the version is the feature version. // Major versions of early Access builds have an "-ea" suffix.