From 725516d433083c88da8073f87cfa2403de9610c9 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 21 Dec 2018 15:09:03 +0100 Subject: [PATCH 01/10] Reorganize the dependencies a bit for better readability --- examples/strict/pom.xml | 68 ++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/examples/strict/pom.xml b/examples/strict/pom.xml index 46a152e0089f4..e51670f082545 100644 --- a/examples/strict/pom.xml +++ b/examples/strict/pom.xml @@ -31,16 +31,6 @@ An example that only contains features that can be run without using -H:+ReportUnsupportedElementsAtRuntime - - org.jboss.shamrock - common-jpa-entities - ${project.version} - - - org.jboss.shamrock - shamrock-jaxrs-deployment - provided - org.jboss.shamrock shamrock-class-transformer-example @@ -66,54 +56,66 @@ provided - org.jboss.resteasy - resteasy-json-p-provider - - - org.jboss.resteasy - resteasy-jackson2-provider + org.jboss.shamrock + shamrock-arc-deployment + provided - org.jboss.resteasy - resteasy-jaxb-provider + org.jboss.shamrock + shamrock-health-deployment + provided - org.glassfish - javax.json + org.jboss.shamrock + shamrock-reactive-streams-operators-deployment org.jboss.shamrock - shamrock-jpa-deployment + shamrock-bean-validation-deployment provided org.jboss.shamrock - shamrock-arc-deployment + shamrock-transactions-deployment provided org.jboss.shamrock - shamrock-health-deployment + shamrock-websockets-deployment provided org.jboss.shamrock - shamrock-reactive-streams-operators-deployment + shamrock-fault-tolerance-deployment + provided org.jboss.shamrock - shamrock-bean-validation-deployment + shamrock-scheduler-deployment provided + + org.jboss.shamrock - shamrock-transactions-deployment + shamrock-jaxrs-deployment provided - org.jboss.shamrock - shamrock-websockets-deployment - provided + org.jboss.resteasy + resteasy-json-p-provider + + + org.jboss.resteasy + resteasy-jackson2-provider + + + org.jboss.resteasy + resteasy-jaxb-provider + + + org.glassfish + javax.json org.jboss.resteasy @@ -124,9 +126,11 @@ shamrock-rest-client-deployment provided + + org.jboss.shamrock - shamrock-fault-tolerance-deployment + shamrock-jpa-deployment provided @@ -136,8 +140,8 @@ org.jboss.shamrock - shamrock-scheduler-deployment - provided + common-jpa-entities + ${project.version} From fc8c4188217d8a2199c0e8a2161ae5f63e8cf7c4 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 21 Dec 2018 16:05:51 +0100 Subject: [PATCH 02/10] Some cleanup in the JPA tests --- .../java/org/jboss/shamrock/example/jpa/Customer.java | 10 ---------- .../shamrock/example/jpa/JPATestBootstrapEndpoint.java | 5 ----- .../example/jpa/JPATestEMInjectionEndpoint.java | 5 ----- .../example/jpa/JPATestReflectionEndpoint.java | 4 ++-- .../jpa/tests/configurationless/CRUDResource.java | 2 +- .../configurationless/JPAConfigurationlessTest.java | 6 +++--- .../JPAConfigurationlessTestInGraalITCase.java | 9 +++++++++ 7 files changed, 15 insertions(+), 26 deletions(-) create mode 100644 jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTestInGraalITCase.java diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/Customer.java b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/Customer.java index adefa19a73542..593d41f7a94c4 100644 --- a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/Customer.java +++ b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/Customer.java @@ -34,16 +34,6 @@ public class Customer extends Human { private Address address; private WorkAddress workAddress; - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - // Address is referenced but not marked as @Embeddable @Embedded public Address getAddress() { diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java index a80a6fb0b9681..0f4c906817915 100644 --- a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java +++ b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java @@ -60,7 +60,6 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO resp.getWriter().write("OK"); } - public void testStoreLoadOnJPA() throws Exception { doStuffWithHibernate( entityManagerFactory ); System.out.println( "Hibernate EntityManagerFactory: shut down" ); @@ -115,10 +114,6 @@ private static String randomName() { return UUID.randomUUID().toString(); } - private void reportException(final Exception e, final HttpServletResponse resp) throws IOException { - reportException(null, e, resp); - } - private void reportException(String errorMessage, final Exception e, final HttpServletResponse resp) throws IOException { final PrintWriter writer = resp.getWriter(); if ( errorMessage != null ) { diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestEMInjectionEndpoint.java b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestEMInjectionEndpoint.java index 16afd521a876e..c4e630b5f9a7c 100644 --- a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestEMInjectionEndpoint.java +++ b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestEMInjectionEndpoint.java @@ -55,7 +55,6 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO resp.getWriter().write("OK"); } - public void testStoreLoadOnJPA() throws Exception { doStuffWithHibernate(); System.out.println("Hibernate EntityManagerFactory: shut down"); @@ -100,10 +99,6 @@ private static String randomName() { return UUID.randomUUID().toString(); } - private void reportException(final Exception e, final HttpServletResponse resp) throws IOException { - reportException(null, e, resp); - } - private void reportException(String errorMessage, final Exception e, final HttpServletResponse resp) throws IOException { final PrintWriter writer = resp.getWriter(); if (errorMessage != null) { diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestReflectionEndpoint.java b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestReflectionEndpoint.java index bdc8423df0082..5231e49d6f2e9 100644 --- a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestReflectionEndpoint.java +++ b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestReflectionEndpoint.java @@ -66,8 +66,8 @@ private void makeSureEntitiesAreAccessibleViaReflection(HttpServletResponse resp if (id.get(instance) != null) { resp.getWriter().write("id should be reachable and null"); } - Method setter = custClass.getDeclaredMethod("setName", String.class); - Method getter = custClass.getDeclaredMethod("getName"); + Method setter = custClass.getMethod("setName", String.class); + Method getter = custClass.getMethod("getName"); setter.invoke(instance, "Emmanuel"); if (! "Emmanuel".equals(getter.invoke(instance))) { resp.getWriter().write("getter / setter should be reachable and usable"); diff --git a/jpa/integrationtests/src/main/java/org/shamrock/jpa/tests/configurationless/CRUDResource.java b/jpa/integrationtests/src/main/java/org/shamrock/jpa/tests/configurationless/CRUDResource.java index fbb7d15663e6e..12d56ee9e18a8 100644 --- a/jpa/integrationtests/src/main/java/org/shamrock/jpa/tests/configurationless/CRUDResource.java +++ b/jpa/integrationtests/src/main/java/org/shamrock/jpa/tests/configurationless/CRUDResource.java @@ -20,7 +20,7 @@ public class CRUDResource { @Inject - private EntityManager em; + EntityManager em; @Inject UserTransaction transaction; diff --git a/jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTest.java b/jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTest.java index 6ae18d2f9116c..17a75c1df2e2c 100644 --- a/jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTest.java +++ b/jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTest.java @@ -6,7 +6,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.StringContains.containsString; /** * @author Emmanuel Bernard emmanuel@hibernate.org @@ -17,8 +17,8 @@ public class JPAConfigurationlessTest { @Test public void testInjection() { String result = URLTester.relative("jpa-test").invokeURL().asString(); - Assert.assertThat(result.contains("jpa=OK"), is(true)); + Assert.assertThat(result, containsString("jpa=OK")); result = URLTester.relative("jpa-test/user-tx").invokeURL().asString(); - Assert.assertThat(result.contains("jpa=OK"), is(true)); + Assert.assertThat(result, containsString("jpa=OK")); } } diff --git a/jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTestInGraalITCase.java b/jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTestInGraalITCase.java new file mode 100644 index 0000000000000..c74864f58210c --- /dev/null +++ b/jpa/integrationtests/src/test/java/org/shamrock/jpa/tests/configurationless/JPAConfigurationlessTestInGraalITCase.java @@ -0,0 +1,9 @@ +package org.shamrock.jpa.tests.configurationless; + +import org.jboss.shamrock.test.SubstrateTest; +import org.junit.runner.RunWith; + +@RunWith(SubstrateTest.class) +public class JPAConfigurationlessTestInGraalITCase extends JPAConfigurationlessTest { + +} From 6a9f846b878bc3eddc0a8fe576156d7ce999f753 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 22 Dec 2018 21:02:53 +0100 Subject: [PATCH 03/10] Clean up the test framework and prepare it for test resource management In passing, fix a few corner cases when testing failed deployment. --- .../test/AbstractShamrockRunListener.java | 80 +++++++ .../test/AbstractShamrockTestRunner.java | 41 ++++ .../jboss/shamrock/test/PathTestHelper.java | 31 +++ .../org/jboss/shamrock/test/ShamrockTest.java | 89 +++---- .../jboss/shamrock/test/ShamrockUnitTest.java | 217 ++++++++++-------- .../jboss/shamrock/test/SubstrateTest.java | 182 +++++++-------- 6 files changed, 374 insertions(+), 266 deletions(-) create mode 100644 test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java create mode 100644 test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockTestRunner.java create mode 100644 test-framework/junit/src/main/java/org/jboss/shamrock/test/PathTestHelper.java diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java new file mode 100644 index 0000000000000..3828123a67955 --- /dev/null +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java @@ -0,0 +1,80 @@ +package org.jboss.shamrock.test; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.runner.Description; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; +import org.junit.runner.notification.RunNotifier; + +abstract class AbstractShamrockRunListener extends RunListener { + + private final Class testClass; + + private final RunNotifier runNotifier; + + private boolean started = false; + + private boolean failed = false; + + protected AbstractShamrockRunListener(Class testClass, RunNotifier runNotifier) { + this.testClass = testClass; + this.runNotifier = runNotifier; + } + + @Override + public void testStarted(Description description) throws Exception { + if (!started) { + List stopListeners = new ArrayList<>(); + + try { + startShamrock(); + started = true; + stopListeners.add(0, new RunListener() { + @Override + public void testRunFinished(Result result) throws Exception { + try { + stopShamrock(); + } catch (Exception e) { + System.err.println("Unable to stop Shamrock"); + } + } + + @Override + public void testFailure(Failure failure) throws Exception { + try { + stopShamrock(); + } catch (Exception e) { + System.err.println("Unable to stop Shamrock"); + } + } + }); + } catch (Exception e) { + failed = true; + throw new RuntimeException("Unable to boot Shamrock", e); + } finally { + for (RunListener stopListener : stopListeners) { + runNotifier.addListener(stopListener); + } + } + } + } + + protected abstract void startShamrock() throws Exception; + + protected abstract void stopShamrock() throws Exception; + + protected Class getTestClass() { + return testClass; + } + + protected boolean isFailed() { + return failed; + } + + protected RunNotifier getRunNotifier() { + return runNotifier; + } +} diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockTestRunner.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockTestRunner.java new file mode 100644 index 0000000000000..0f1622fb4c1c1 --- /dev/null +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockTestRunner.java @@ -0,0 +1,41 @@ +package org.jboss.shamrock.test; + +import java.util.function.BiFunction; + +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; + +abstract class AbstractShamrockTestRunner extends BlockJUnit4ClassRunner { + + private static boolean first = true; + private static AbstractShamrockRunListener shamrockRunListener; + + private final BiFunction, RunNotifier, AbstractShamrockRunListener> shamrockRunListenerSupplier; + + public AbstractShamrockTestRunner(Class klass, BiFunction, RunNotifier, AbstractShamrockRunListener> shamrockRunListenerSupplier) throws InitializationError { + super(klass); + this.shamrockRunListenerSupplier = shamrockRunListenerSupplier; + } + + @Override + public void run(final RunNotifier notifier) { + if (first) { + first = false; + shamrockRunListener = shamrockRunListenerSupplier.apply(getTestClass().getJavaClass(), notifier); + notifier.addListener(shamrockRunListener); + } + + super.run(notifier); + } + + @Override + protected void runChild(final FrameworkMethod method, RunNotifier notifier) { + if (!shamrockRunListener.isFailed()) { + super.runChild(method, notifier); + } else { + notifier.fireTestIgnored(describeChild(method)); + } + } +} diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/PathTestHelper.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/PathTestHelper.java new file mode 100644 index 0000000000000..7c81133a50739 --- /dev/null +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/PathTestHelper.java @@ -0,0 +1,31 @@ +package org.jboss.shamrock.test; + +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +final class PathTestHelper { + + private static final String TEST_CLASSES_FRAGMENT = "/test-classes"; + private static final String CLASSES_FRAGMENT = "/classes"; + + private PathTestHelper() { + } + + public static final Path getTestClassesLocation(Class testClass) { + String classFileName = testClass.getName().replace('.', '/') + ".class"; + URL resource = testClass.getClassLoader().getResource(classFileName); + + String path = resource.getPath(); + + if (!path.contains(TEST_CLASSES_FRAGMENT)) { + throw new RuntimeException("The test class " + testClass + " is not located in the " + TEST_CLASSES_FRAGMENT + " directory."); + } + + return Paths.get(resource.getPath().substring(0, resource.getPath().length() - classFileName.length())); + } + + public static final Path getAppClassLocation(Class testClass) { + return Paths.get(getTestClassesLocation(testClass).toString().replace(TEST_CLASSES_FRAGMENT, CLASSES_FRAGMENT)); + } +} diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTest.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTest.java index b76797f4bf0e7..33ee673ba833c 100644 --- a/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTest.java +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTest.java @@ -16,83 +16,48 @@ package org.jboss.shamrock.test; -import java.net.URL; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; +import static org.jboss.shamrock.test.PathTestHelper.getTestClassesLocation; +import static org.jboss.shamrock.test.PathTestHelper.getAppClassLocation; + +import java.io.IOException; +import java.util.Collections; import org.jboss.shamrock.runner.RuntimeRunner; import org.junit.runner.Description; import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; -import org.junit.runners.BlockJUnit4ClassRunner; -import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; -public class ShamrockTest extends BlockJUnit4ClassRunner { - - static boolean first = true; - static boolean started = false; - static boolean failed = false; +public class ShamrockTest extends AbstractShamrockTestRunner { - /** - * Creates a BlockJUnit4ClassRunner to run {@code klass} - * - * @param klass - * @throws InitializationError if the test class is malformed. - */ public ShamrockTest(Class klass) throws InitializationError { - super(klass); + super(klass, (c, n) -> new ShamrockRunListener(c, n)); } - @Override - public void run(final RunNotifier notifier) { - runInternal(notifier); - super.run(notifier); - } + private static class ShamrockRunListener extends AbstractShamrockRunListener { - @Override - protected void runChild(final FrameworkMethod method, RunNotifier notifier) { - if (!failed) { - super.runChild(method, notifier); - } else { - notifier.fireTestIgnored(describeChild(method)); - } - } + private RuntimeRunner runtimeRunner; - private void runInternal(RunNotifier notifier) { - if (first) { - first = false; - //now we need to bootstrap shamrock - notifier.addListener(new RunListener() { + ShamrockRunListener(Class testClass, RunNotifier runNotifier) { + super(testClass, runNotifier); + } + @Override + protected void startShamrock() { + if (ShamrockUnitTest.started) { + getRunNotifier().fireTestFailure(new Failure(Description.createSuiteDescription(ShamrockTest.class), + new RuntimeException("Cannot mix ShamrockTest and ShamrockUnitTest in the same test suite"))); + return; + } + + runtimeRunner = new RuntimeRunner(getClass().getClassLoader(), getAppClassLocation(getTestClass()), + getTestClassesLocation(getTestClass()), null, Collections.emptyList()); + runtimeRunner.run(); + } - @Override - public void testStarted(Description description) { - if (ShamrockUnitTest.started) { - notifier.fireTestFailure(new Failure(Description.createSuiteDescription(ShamrockTest.class), new RuntimeException("Cannot mix ShamrockTest and ShamrockUnitTest in the same test suite"))); - return; - } - if (!started) { - started = true; - //TODO: so much hacks... - try { - Class theClass = description.getTestClass(); - String classFileName = theClass.getName().replace('.', '/') + ".class"; - URL resource = theClass.getClassLoader().getResource(classFileName); - String testClassLocation = resource.getPath().substring(0, resource.getPath().length() - classFileName.length()); - String appClassLocation = testClassLocation.replace("test-classes", "classes"); - Path appRoot = Paths.get(appClassLocation); - RuntimeRunner runtimeRunner = new RuntimeRunner(getClass().getClassLoader(), appRoot, Paths.get(testClassLocation), null, new ArrayList<>()); - runtimeRunner.run(); - } catch (RuntimeException e) { - failed = true; - throw new RuntimeException("Failed to boot Shamrock during @ShamrockTest runner!", e); - } - } - } - }); + @Override + protected void stopShamrock() throws IOException { + runtimeRunner.close(); } } } diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockUnitTest.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockUnitTest.java index 0dc8d8b0f9c94..85654dfb69021 100644 --- a/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockUnitTest.java +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockUnitTest.java @@ -16,19 +16,19 @@ package org.jboss.shamrock.test; +import static org.jboss.shamrock.test.PathTestHelper.getTestClassesLocation; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.net.URL; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Comparator; @@ -40,6 +40,7 @@ import org.jboss.shrinkwrap.api.exporter.ExplodedExporter; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; @@ -51,12 +52,16 @@ public class ShamrockUnitTest extends BlockJUnit4ClassRunner { System.setProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager"); } - private static Path deploymentDir; - private static RuntimeRunner runtimeRunner; - static boolean started = false; + // We need to have them static as they are accessed from the super constructor call. + // It will do as long as we keep the test execution sequential and don't parallelize things. + private static RuntimeRunner runtimeRunner; + private static Path deploymentDir; + private static BuildShouldFailWith buildShouldFailWith; + public ShamrockUnitTest(Class klass) throws InitializationError { + // We need to do it this way as we need to refresh the class once Shamrock is started super(doSetup(klass)); } @@ -65,60 +70,36 @@ protected Object createTest() throws Exception { InjectionInstance factory = InjectionFactoryTemplate.currentFactory().create(getTestClass().getJavaClass()); return factory.newInstance(); } - + @Override - protected boolean isIgnored(FrameworkMethod child) { - return !started || super.isIgnored(child); + protected void runChild(final FrameworkMethod method, RunNotifier notifier) { + if (started) { + super.runChild(method, notifier); + } else if (buildShouldFailWith != null) { + notifier.fireTestFinished(describeChild(method)); + } else { + notifier.fireTestIgnored(describeChild(method)); + } } - static Class doSetup(Class clazz) { - try { - Class theClass = clazz; - Method deploymentMethod = null; - for (Method m : theClass.getMethods()) { - if (m.isAnnotationPresent(Deployment.class)) { - deploymentMethod = m; - break; - } - } - if (deploymentMethod == null) { - throw new RuntimeException("Could not find @Deployment method on " + theClass); - } - if (!Modifier.isStatic(deploymentMethod.getModifiers())) { - throw new RuntimeException("@Deployment method must be static" + deploymentMethod); - } + @Override + protected Statement withAfterClasses(Statement statement) { + Statement existing = super.withAfterClasses(statement); - JavaArchive archive = (JavaArchive) deploymentMethod.invoke(null); - archive.addClass(theClass); + return new StopShamrockAndCleanDeploymentDirStatement(existing); + } + + private static Class doSetup(Class testClass) { + try { deploymentDir = Files.createTempDirectory("shamrock-unit-test"); + Method deploymentMethod = getDeploymentMethod(testClass); + buildShouldFailWith = deploymentMethod.getAnnotation(BuildShouldFailWith.class); - archive.as(ExplodedExporter.class).exportExplodedInto(deploymentDir.toFile()); + exportArchive(deploymentDir, testClass, deploymentMethod); - String exportPath = System.getProperty("shamrock.deploymentExportPath"); - if (exportPath != null) { - File exportDir = new File(exportPath); - if (exportDir.exists()) { - if (!exportDir.isDirectory()) { - throw new IllegalStateException("Export path is not a directory: " + exportPath); - } - Files.walk(exportDir.toPath()) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } else if (!exportDir.mkdirs()) { - throw new IllegalStateException("Export path could not be created: " + exportPath); - } - File exportFile = new File(exportDir, archive.getName()); - archive.as(ZipExporter.class) - .exportTo(exportFile); - } - - String classFileName = theClass.getName().replace('.', '/') + ".class"; - URL resource = theClass.getClassLoader().getResource(classFileName); - String testClassLocation = resource.getPath().substring(0, resource.getPath().length() - classFileName.length()); - runtimeRunner = new RuntimeRunner(clazz.getClassLoader(), deploymentDir, Paths.get(testClassLocation), null, new ArrayList<>()); + runtimeRunner = new RuntimeRunner(testClass.getClassLoader(), deploymentDir, + getTestClassesLocation(testClass), null, new ArrayList<>()); - BuildShouldFailWith buildShouldFailWith = deploymentMethod.getAnnotation(BuildShouldFailWith.class); try { runtimeRunner.run(); if (buildShouldFailWith != null) { @@ -131,8 +112,8 @@ static Class doSetup(Class clazz) { if (e instanceof RuntimeException) { Throwable cause = e.getCause(); if (cause != null && cause instanceof BuildException) { - assertEquals("Build failed with wrong exception", buildShouldFailWith.value(), cause.getCause() - .getClass()); + assertEquals("Build failed with wrong exception", buildShouldFailWith.value(), + cause.getCause().getClass()); } else { fail("Build did not fail with build exception: " + e); } @@ -144,68 +125,102 @@ static Class doSetup(Class clazz) { } } - String javaClass = clazz.getName(); - return Class.forName(javaClass, true, Thread.currentThread().getContextClassLoader()); + // refresh the class + return Class.forName(testClass.getName(), true, Thread.currentThread().getContextClassLoader()); + } catch (RuntimeException e) { + throw e; } catch (Exception e) { throw new RuntimeException(e); } } - @Override - protected Statement withBeforeClasses(Statement statement) { - Statement existing = super.withBeforeClasses(statement); - return new Statement() { - @Override - public void evaluate() throws Throwable { + private static Method getDeploymentMethod(Class testClass) { + for (Method method : testClass.getMethods()) { + if (method.isAnnotationPresent(Deployment.class)) { + if (!Modifier.isStatic(method.getModifiers())) { + throw new RuntimeException("@Deployment method must be static" + method); + } - existing.evaluate(); + return method; + } + } + + throw new RuntimeException("Could not find @Deployment method on " + testClass); + } + + private static void exportArchive(Path deploymentDir, Class testClass, Method deploymentMethod) { + try { + JavaArchive archive = (JavaArchive) deploymentMethod.invoke(null); + archive.addClass(testClass); + archive.as(ExplodedExporter.class).exportExplodedInto(deploymentDir.toFile()); + String exportPath = System.getProperty("shamrock.deploymentExportPath"); + if (exportPath != null) { + File exportDir = new File(exportPath); + if (exportDir.exists()) { + if (!exportDir.isDirectory()) { + throw new IllegalStateException("Export path is not a directory: " + exportPath); + } + Files.walk(exportDir.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile) + .forEach(File::delete); + } else if (!exportDir.mkdirs()) { + throw new IllegalStateException("Export path could not be created: " + exportPath); + } + File exportFile = new File(exportDir, archive.getName()); + archive.as(ZipExporter.class).exportTo(exportFile); } - }; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IOException e) { + throw new RuntimeException("Unable to create the archive", e); + } } - @Override - protected Statement withAfterClasses(Statement statement) { - Statement existing = super.withAfterClasses(statement); - return new Statement() { - @Override - public void evaluate() throws Throwable { + private class StopShamrockAndCleanDeploymentDirStatement extends Statement { + + private final Statement existing; + + + private StopShamrockAndCleanDeploymentDirStatement(Statement existing) { + this.existing = existing; + } + + @Override + public void evaluate() throws Throwable { + try { + existing.evaluate(); + } finally { try { - existing.evaluate(); + if (runtimeRunner != null) { + runtimeRunner.close(); + } } finally { - try { - if (runtimeRunner != null) { - runtimeRunner.close(); - } - } finally { - if (deploymentDir != null) { - Files.walkFileTree(deploymentDir, new FileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); - } + if (deploymentDir != null) { + Files.walkFileTree(deploymentDir, new FileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); } } } - }; + } } } diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/SubstrateTest.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/SubstrateTest.java index 0dc770adc4ba5..3def73f5fc718 100644 --- a/test-framework/junit/src/main/java/org/jboss/shamrock/test/SubstrateTest.java +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/SubstrateTest.java @@ -24,127 +24,103 @@ import java.net.URL; import java.net.URLClassLoader; -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; import org.junit.runner.notification.RunNotifier; -import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.InitializationError; /** - * A test runner for Graal native images - * basically just a big pile of hacks + * A test runner for GraalVM native images. */ -public class SubstrateTest extends BlockJUnit4ClassRunner { +public class SubstrateTest extends AbstractShamrockTestRunner { private static final long IMAGE_WAIT_TIME = 60000; - private static boolean first = true; - private static boolean started = false; - - /** - * Creates a BlockJUnit4ClassRunner to run {@code klass} - * - * @param klass - * @throws InitializationError if the test class is malformed. - */ public SubstrateTest(Class klass) throws InitializationError { - super(klass); + super(klass, (c , n) -> new ShamrockNativeImageRunListener(c, n)); } - @Override - public void run(final RunNotifier notifier) { + private static class ShamrockNativeImageRunListener extends AbstractShamrockRunListener { + + private Process shamrockProcess; + + ShamrockNativeImageRunListener(Class testClass, RunNotifier runNotifier) { + super(testClass, runNotifier); + } + + @Override + protected void startShamrock() throws IOException { + String path = System.getProperty("native.image.path"); + if (path == null) { + path = guessPath(getTestClass()); + } + + System.out.println("Executing " + path); - runInternal(notifier); - super.run(notifier); + shamrockProcess = Runtime.getRuntime().exec(path); + new Thread(new ProcessReader(shamrockProcess.getInputStream())).start(); + new Thread(new ProcessReader(shamrockProcess.getErrorStream())).start(); + + waitForShamrock(); + } + + @Override + protected void stopShamrock() { + shamrockProcess.destroy(); + } } - private void runInternal(RunNotifier notifier) { - if (first) { - first = false; - notifier.addListener(new RunListener() { - - - @Override - public void testStarted(Description description) throws Exception { - if (!started) { - started = true; - String path = System.getProperty("native.image.path"); - if (path == null) { - //ok, lets make a guess - //this is a horrible hack, but it is intended to make this work in IDE's - - ClassLoader cl = getClass().getClassLoader(); - String guessedPath = null; - if (cl instanceof URLClassLoader) { - URL[] urls = ((URLClassLoader) cl).getURLs(); - for (URL url : urls) { - if (url.getProtocol().equals("file") && url.getPath().endsWith("test-classes/")) { - //we have the test classes dir - File testClasses = new File(url.getPath()); - for (File file : testClasses.getParentFile().listFiles()) { - if (file.getName().endsWith("-runner")) { - guessedPath = file.getAbsolutePath(); - break; - } - } - } - if (guessedPath != null) { - break; - } - } - } - - if (guessedPath == null) { - notifier.fireTestFailure(new Failure(Description.createSuiteDescription(SubstrateTest.class), new RuntimeException("Unable to find native image, make sure native.image.path is set"))); - return; - } else { - String errorString = "\n=native.image.path was not set, making a guess that " + guessedPath + " is the correct native image="; - for (int i = 0; i < errorString.length(); ++i) { - System.err.print("="); - } - System.err.println(errorString); - for (int i = 0; i < errorString.length(); ++i) { - System.err.print("="); - } - System.err.println(); - path = guessedPath; - } - } - System.out.println("Executing " + path); - final Process testProcess = Runtime.getRuntime().exec(path); - notifier.addListener(new RunListener() { - @Override - public void testRunFinished(Result result) throws Exception { - super.testRunFinished(result); - testProcess.destroy(); - } - }); - new Thread(new ProcessReader(testProcess.getInputStream())).start(); - new Thread(new ProcessReader(testProcess.getErrorStream())).start(); - - int port = Integer.getInteger("http.port", 8080); - long bailout = System.currentTimeMillis() + IMAGE_WAIT_TIME; - boolean ok = false; - while (System.currentTimeMillis() < bailout) { - try { - Thread.sleep(100); - try (Socket s = new Socket()) { - s.connect(new InetSocketAddress("localhost", port)); - ok = true; - break; - } - } catch (Exception expected) { - } - } - if (!ok) { - throw new RuntimeException("Unable to start native image in " + IMAGE_WAIT_TIME + "ms"); + private static String guessPath(Class testClass) { + //ok, lets make a guess + //this is a horrible hack, but it is intended to make this work in IDE's + + ClassLoader cl = testClass.getClassLoader(); + + if (cl instanceof URLClassLoader) { + URL[] urls = ((URLClassLoader) cl).getURLs(); + for (URL url : urls) { + if (url.getProtocol().equals("file") && url.getPath().endsWith("test-classes/")) { + //we have the test classes dir + File testClasses = new File(url.getPath()); + for (File file : testClasses.getParentFile().listFiles()) { + if (file.getName().endsWith("-runner")) { + logGuessedPath(file.getAbsolutePath()); + return file.getAbsolutePath(); } } } - }); + } + } + + throw new RuntimeException("Unable to find native image, make sure native.image.path is set"); + } + + private static void logGuessedPath(String guessedPath) { + String errorString = "\n=native.image.path was not set, making a guess that " + guessedPath + " is the correct native image="; + for (int i = 0; i < errorString.length(); ++i) { + System.err.print("="); + } + System.err.println(errorString); + for (int i = 0; i < errorString.length(); ++i) { + System.err.print("="); + } + System.err.println(); + } + + private static void waitForShamrock() { + int port = Integer.getInteger("http.port", 8080); + long bailout = System.currentTimeMillis() + IMAGE_WAIT_TIME; + + while (System.currentTimeMillis() < bailout) { + try { + Thread.sleep(100); + try (Socket s = new Socket()) { + s.connect(new InetSocketAddress("localhost", port)); + return; + } + } catch (Exception expected) { + } } + + throw new RuntimeException("Unable to start native image in " + IMAGE_WAIT_TIME + "ms"); } private static final class ProcessReader implements Runnable { From 3b70a6556909d99c96f8f9a20ab51af10133b1f7 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 22 Dec 2018 21:04:17 +0100 Subject: [PATCH 04/10] Implement test resource management in our test framework Note that this requires to index the test classes with Jandex. --- test-framework/junit/pom.xml | 4 + .../test/AbstractShamrockRunListener.java | 163 +++++++++++++++--- .../shamrock/test/ShamrockTestResource.java | 32 ++++ .../ShamrockTestResourceLifecycleManager.java | 17 ++ 4 files changed, 195 insertions(+), 21 deletions(-) create mode 100644 test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResource.java create mode 100644 test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResourceLifecycleManager.java diff --git a/test-framework/junit/pom.xml b/test-framework/junit/pom.xml index 21692ba211083..052cefe6880d0 100644 --- a/test-framework/junit/pom.xml +++ b/test-framework/junit/pom.xml @@ -49,6 +49,10 @@ org.glassfish javax.json + + org.jboss + jandex + diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java index 3828123a67955..f4db32f7e2dab 100644 --- a/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/AbstractShamrockRunListener.java @@ -1,8 +1,25 @@ package org.jboss.shamrock.test; +import static org.jboss.shamrock.test.PathTestHelper.getTestClassesLocation; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; +import org.jboss.jandex.Indexer; import org.junit.runner.Description; import org.junit.runner.Result; import org.junit.runner.notification.Failure; @@ -15,6 +32,8 @@ abstract class AbstractShamrockRunListener extends RunListener { private final RunNotifier runNotifier; + private final Set testResources; + private boolean started = false; private boolean failed = false; @@ -22,6 +41,7 @@ abstract class AbstractShamrockRunListener extends RunListener { protected AbstractShamrockRunListener(Class testClass, RunNotifier runNotifier) { this.testClass = testClass; this.runNotifier = runNotifier; + this.testResources = getTestResources(testClass); } @Override @@ -30,30 +50,60 @@ public void testStarted(Description description) throws Exception { List stopListeners = new ArrayList<>(); try { - startShamrock(); - started = true; - stopListeners.add(0, new RunListener() { - @Override - public void testRunFinished(Result result) throws Exception { - try { - stopShamrock(); - } catch (Exception e) { - System.err.println("Unable to stop Shamrock"); - } + for (ShamrockTestResourceLifecycleManager testResource : testResources) { + try { + testResource.start(); + } catch (Exception e) { + failed = true; + throw new RuntimeException("Unable to start Shamrock test resource " + testResource); } + stopListeners.add(0, new RunListener() { + @Override + public void testRunFinished(Result result) throws Exception { + try { + testResource.stop(); + } catch (Exception e) { + System.err.println("Unable to stop Shamrock test resource " + testResource); + } + } - @Override - public void testFailure(Failure failure) throws Exception { - try { - stopShamrock(); - } catch (Exception e) { - System.err.println("Unable to stop Shamrock"); + @Override + public void testFailure(Failure failure) throws Exception { + try { + testResource.stop(); + } catch (Exception e) { + System.err.println("Unable to stop Shamrock test resource " + testResource); + } } - } - }); - } catch (Exception e) { - failed = true; - throw new RuntimeException("Unable to boot Shamrock", e); + }); + } + + try { + startShamrock(); + started = true; + stopListeners.add(0, new RunListener() { + @Override + public void testRunFinished(Result result) throws Exception { + try { + stopShamrock(); + } catch (Exception e) { + System.err.println("Unable to stop Shamrock"); + } + } + + @Override + public void testFailure(Failure failure) throws Exception { + try { + stopShamrock(); + } catch (Exception e) { + System.err.println("Unable to stop Shamrock"); + } + } + }); + } catch (Exception e) { + failed = true; + throw new RuntimeException("Unable to boot Shamrock", e); + } } finally { for (RunListener stopListener : stopListeners) { runNotifier.addListener(stopListener); @@ -77,4 +127,75 @@ protected boolean isFailed() { protected RunNotifier getRunNotifier() { return runNotifier; } + + @SuppressWarnings("unchecked") + private Set getTestResources(Class testClass) { + IndexView index = indexTestClasses(testClass); + + Set> testResourceRunnerClasses = new LinkedHashSet<>(); + + for (AnnotationInstance annotation : index.getAnnotations(DotName.createSimple(ShamrockTestResource.class.getName()))) { + try { + testResourceRunnerClasses.add((Class) Class + .forName(annotation.value().asString())); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Unable to find the class for the test resource " + annotation.value().asString()); + } + } + + Set testResourceRunners = new LinkedHashSet<>(); + + for (Class testResourceRunnerClass : testResourceRunnerClasses) { + try { + testResourceRunners.add(testResourceRunnerClass.getConstructor().newInstance()); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + throw new RuntimeException("Unable to instantiate the test resource " + testResourceRunnerClass); + } + } + + return testResourceRunners; + } + + private IndexView indexTestClasses(Class testClass) { + Indexer indexer = new Indexer(); + + try { + Files.walkFileTree(getTestClassesLocation(testClass), new FileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) + throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (!file.toString().endsWith(".class")) { + return FileVisitResult.CONTINUE; + } + try(InputStream inputStream = Files.newInputStream(file, StandardOpenOption.READ)) { + indexer.index(inputStream); + } + catch (Exception e) { + // ignore + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + throw new RuntimeException("Unable to index the test-classes/ directory.", e); + } + + return indexer.complete(); + } } diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResource.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResource.java new file mode 100644 index 0000000000000..3c8111939e701 --- /dev/null +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResource.java @@ -0,0 +1,32 @@ +package org.jboss.shamrock.test; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.jboss.shamrock.test.ShamrockTestResource.List; + +/** + * Used to define a test resource. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Repeatable(List.class) +public @interface ShamrockTestResource { + + /** + * @return The class managing the lifecycle of the test resource. + */ + Class value(); + + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + @Documented + @interface List { + ShamrockTestResource[] value(); + } +} diff --git a/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResourceLifecycleManager.java b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResourceLifecycleManager.java new file mode 100644 index 0000000000000..4fbe44d2baa09 --- /dev/null +++ b/test-framework/junit/src/main/java/org/jboss/shamrock/test/ShamrockTestResourceLifecycleManager.java @@ -0,0 +1,17 @@ +package org.jboss.shamrock.test; + +/** + * Manage the lifecycle of a test resource, for instance a H2 test server. + */ +public interface ShamrockTestResourceLifecycleManager { + + /** + * Start the test resource. + */ + void start(); + + /** + * Stop the test resource. + */ + void stop(); +} From b0f906d9363f93fcc42736a432e8f1c39dd77d06 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Fri, 21 Dec 2018 16:09:35 +0100 Subject: [PATCH 05/10] Use H2 to run the JPA integration tests and the strict example For the strict example, it's still possible to test with PostgreSQL by using -Dtest-postgresql (and -Ddocker if you want to start a Docker container). --- azure-pipelines.yml | 2 +- .../example/test/JPAFunctionalityTest.java | 5 -- .../testutils/H2DatabaseLifecycleManager.java | 42 ----------- ...2DatabaseTestResourceLifecycleManager.java | 33 +++++++++ examples/strict/pom.xml | 37 ++++++++-- .../META-INF/microprofile-config.properties | 8 +-- ...2DatabaseTestResourceLifecycleManager.java | 33 +++++++++ jpa/integrationtests/pom.xml | 69 +------------------ .../META-INF/microprofile-config.properties | 9 +-- ...2DatabaseTestResourceLifecycleManager.java | 33 +++++++++ 10 files changed, 141 insertions(+), 130 deletions(-) delete mode 100644 examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseLifecycleManager.java create mode 100644 examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java create mode 100644 examples/strict/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java create mode 100644 jpa/integrationtests/src/test/java/org/shamrock/jpa/testutils/H2DatabaseTestResourceLifecycleManager.java diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8d81af5f05e4b..a07c45bc0c5f2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,7 +21,7 @@ jobs: displayName: 'Maven Build' inputs: goals: 'install' - options: '--settings azure-mvn-settings.xml -Dnative-image.docker-build -Dno-postgres -Dnative-image.xmx=4g -Dnative' + options: '--settings azure-mvn-settings.xml -Dnative-image.docker-build -Dtest-postgresql -Dnative-image.xmx=4g -Dnative' - script: | docker build -f docker/strict-example/Dockerfile -t jtgdocker1/shamrock-strict-example examples/strict/ diff --git a/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/test/JPAFunctionalityTest.java b/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/test/JPAFunctionalityTest.java index 848600739ecf7..730c5be35aa47 100644 --- a/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/test/JPAFunctionalityTest.java +++ b/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/test/JPAFunctionalityTest.java @@ -2,10 +2,8 @@ import static org.junit.Assert.assertEquals; -import org.jboss.shamrock.example.testutils.H2DatabaseLifecycleManager; import org.jboss.shamrock.test.ShamrockTest; import org.jboss.shamrock.test.URLTester; -import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; @@ -17,9 +15,6 @@ @RunWith(ShamrockTest.class) public class JPAFunctionalityTest { - @ClassRule - public static final H2DatabaseLifecycleManager h2 = new H2DatabaseLifecycleManager(); - @Test public void testJPAFunctionalityFromServlet() throws Exception { assertEquals("OK", URLTester.relative("jpa-h2/testfunctionality").invokeURL().asString()); diff --git a/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseLifecycleManager.java b/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseLifecycleManager.java deleted file mode 100644 index 57386999cf9a1..0000000000000 --- a/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseLifecycleManager.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.jboss.shamrock.example.testutils; - -import java.sql.SQLException; - -import org.h2.tools.Server; - -/** - * JUnit helper to start the H2 database in server mode (over TCP) - * to be able to test for actual database connection. - * - * @author Sanne Grinovero - */ -public class H2DatabaseLifecycleManager extends org.junit.rules.ExternalResource { - - private int startedContainers = 0; - private Server tcpServer; - - @Override - public synchronized void before() { - if (startedContainers==0) { - try { - tcpServer = Server.createTcpServer(); - tcpServer.start(); - startedContainers++; - System.out.println("H2 database started in TCP server mode"); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - } - - @Override - public synchronized void after() { - startedContainers--; - if (startedContainers==0 && tcpServer!=null) { - tcpServer.stop(); - System.out.println("H2 database was shut down"); - tcpServer = null; - } - } - -} diff --git a/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java b/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java new file mode 100644 index 0000000000000..0d77d4cc981de --- /dev/null +++ b/examples/jpa-h2/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java @@ -0,0 +1,33 @@ +package org.jboss.shamrock.example.testutils; + +import java.sql.SQLException; + +import org.h2.tools.Server; +import org.jboss.shamrock.test.ShamrockTestResource; +import org.jboss.shamrock.test.ShamrockTestResourceLifecycleManager; + +@ShamrockTestResource(H2DatabaseTestResourceLifecycleManager.class) +public class H2DatabaseTestResourceLifecycleManager implements ShamrockTestResourceLifecycleManager { + + private Server tcpServer; + + @Override + public synchronized void start() { + try { + tcpServer = Server.createTcpServer(); + tcpServer.start(); + System.out.println("[INFO] H2 database started in TCP server mode"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public synchronized void stop() { + if (tcpServer != null) { + tcpServer.stop(); + System.out.println("[INFO] H2 database was shut down"); + tcpServer = null; + } + } +} diff --git a/examples/strict/pom.xml b/examples/strict/pom.xml index e51670f082545..9b21148c4e2dd 100644 --- a/examples/strict/pom.xml +++ b/examples/strict/pom.xml @@ -30,6 +30,14 @@ Shamrock - Examples - Strict An example that only contains features that can be run without using -H:+ReportUnsupportedElementsAtRuntime + + + jdbc:h2:tcp://localhost/mem:test + org.h2.Driver + + + + org.jboss.shamrock @@ -135,7 +143,7 @@ org.jboss.shamrock - shamrock-jdbc-postgresql-deployment + shamrock-jdbc-h2-deployment provided @@ -176,6 +184,27 @@ + + test-postgresql + + + test-postgresql + + + + ${postgres.url} + org.postgresql.Driver + hibernate_orm_test + hibernate_orm_test + + + + org.jboss.shamrock + shamrock-jdbc-postgresql-deployment + provided + + + native-image @@ -227,11 +256,12 @@ + - postgres + docker-postgresql - !no-postgres + docker @@ -295,5 +325,4 @@ - diff --git a/examples/strict/src/main/resources/META-INF/microprofile-config.properties b/examples/strict/src/main/resources/META-INF/microprofile-config.properties index 4f599131ba226..3a632bbcd6409 100644 --- a/examples/strict/src/main/resources/META-INF/microprofile-config.properties +++ b/examples/strict/src/main/resources/META-INF/microprofile-config.properties @@ -16,10 +16,10 @@ org.jboss.shamrock.example.rest.RestInterface/mp-rest/url=http://localhost:8080/rest -shamrock.datasource.url: ${postgres.url} -shamrock.datasource.driver: org.postgresql.Driver -shamrock.datasource.username: hibernate_orm_test -shamrock.datasource.password: hibernate_orm_test +shamrock.datasource.url: ${datasource.url} +shamrock.datasource.driver: ${datasource.driver} +shamrock.datasource.username: ${datasource.username} +shamrock.datasource.password: ${datasource.password} web-message=A message schedulerservice.cron.expr=0/10 * * * * ? diff --git a/examples/strict/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java b/examples/strict/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java new file mode 100644 index 0000000000000..0d77d4cc981de --- /dev/null +++ b/examples/strict/src/test/java/org/jboss/shamrock/example/testutils/H2DatabaseTestResourceLifecycleManager.java @@ -0,0 +1,33 @@ +package org.jboss.shamrock.example.testutils; + +import java.sql.SQLException; + +import org.h2.tools.Server; +import org.jboss.shamrock.test.ShamrockTestResource; +import org.jboss.shamrock.test.ShamrockTestResourceLifecycleManager; + +@ShamrockTestResource(H2DatabaseTestResourceLifecycleManager.class) +public class H2DatabaseTestResourceLifecycleManager implements ShamrockTestResourceLifecycleManager { + + private Server tcpServer; + + @Override + public synchronized void start() { + try { + tcpServer = Server.createTcpServer(); + tcpServer.start(); + System.out.println("[INFO] H2 database started in TCP server mode"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public synchronized void stop() { + if (tcpServer != null) { + tcpServer.stop(); + System.out.println("[INFO] H2 database was shut down"); + tcpServer = null; + } + } +} diff --git a/jpa/integrationtests/pom.xml b/jpa/integrationtests/pom.xml index b4b80eabdb1ae..b351b27809ae0 100644 --- a/jpa/integrationtests/pom.xml +++ b/jpa/integrationtests/pom.xml @@ -25,7 +25,7 @@ org.jboss.shamrock - shamrock-jdbc-postgresql-deployment + shamrock-jdbc-h2-deployment provided @@ -107,73 +107,6 @@ - - postgres - - - !no-postgres - - - - jdbc:postgresql://localhost:5431/hibernate_orm_test - - - - - io.fabric8 - docker-maven-plugin - - - - postgres:10.5 - postgresql - - - hibernate_orm_test - hibernate_orm_test - hibernate_orm_test - - - 5431:5432 - - - - mapped - - 5432 - - - - - - - - - true - - - - docker-start - compile - - stop - start - - - - docker-stop - post-integration-test - - stop - - - - - - - - \ No newline at end of file diff --git a/jpa/integrationtests/src/main/resources/META-INF/microprofile-config.properties b/jpa/integrationtests/src/main/resources/META-INF/microprofile-config.properties index 566d64e410f48..d97714132c50a 100644 --- a/jpa/integrationtests/src/main/resources/META-INF/microprofile-config.properties +++ b/jpa/integrationtests/src/main/resources/META-INF/microprofile-config.properties @@ -1,9 +1,6 @@ -shamrock.datasource.url: ${postgres.url} -shamrock.datasource.driver: org.postgresql.Driver -shamrock.datasource.username: hibernate_orm_test -shamrock.datasource.password: hibernate_orm_test +shamrock.datasource.url=jdbc:h2:tcp://localhost/mem:test +shamrock.datasource.driver=org.h2.Driver -#shamrock.hibernate.dialect: org.hibernate.dialect.PostgreSQL95Dialect -shamrock.hibernate.dialect: org.hibernate.dialect.PostgreSQL95Dialect +shamrock.hibernate.dialect: org.hibernate.dialect.H2Dialect shamrock.hibernate.show_sql: true shamrock.hibernate.schema-generation.database.action: drop-and-create diff --git a/jpa/integrationtests/src/test/java/org/shamrock/jpa/testutils/H2DatabaseTestResourceLifecycleManager.java b/jpa/integrationtests/src/test/java/org/shamrock/jpa/testutils/H2DatabaseTestResourceLifecycleManager.java new file mode 100644 index 0000000000000..ad7385d3f431e --- /dev/null +++ b/jpa/integrationtests/src/test/java/org/shamrock/jpa/testutils/H2DatabaseTestResourceLifecycleManager.java @@ -0,0 +1,33 @@ +package org.shamrock.jpa.testutils; + +import java.sql.SQLException; + +import org.h2.tools.Server; +import org.jboss.shamrock.test.ShamrockTestResource; +import org.jboss.shamrock.test.ShamrockTestResourceLifecycleManager; + +@ShamrockTestResource(H2DatabaseTestResourceLifecycleManager.class) +public class H2DatabaseTestResourceLifecycleManager implements ShamrockTestResourceLifecycleManager { + + private Server tcpServer; + + @Override + public synchronized void start() { + try { + tcpServer = Server.createTcpServer(); + tcpServer.start(); + System.out.println("[INFO] H2 database started in TCP server mode"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public synchronized void stop() { + if (tcpServer != null) { + tcpServer.stop(); + System.out.println("[INFO] H2 database was shut down"); + tcpServer = null; + } + } +} From 3bedf8d10ea3e953e69fb1d7bcbf80034fa9ec57 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 22 Dec 2018 21:49:12 +0100 Subject: [PATCH 06/10] Disable testing with MariaDB by default You need to use -Dtest-mariadb to enable testing and -Ddocker to run the MariaDB server in a Docker container. --- examples/jpa-mariadb/pom.xml | 41 ++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/examples/jpa-mariadb/pom.xml b/examples/jpa-mariadb/pom.xml index 2245e070294f3..3126fe00369a2 100644 --- a/examples/jpa-mariadb/pom.xml +++ b/examples/jpa-mariadb/pom.xml @@ -67,6 +67,18 @@ + + maven-surefire-plugin + + true + + + + maven-failsafe-plugin + + true + + ${project.groupId} shamrock-maven-plugin @@ -83,6 +95,31 @@ + + test-mariadb + + + test-mariadb + + + + + + maven-surefire-plugin + + false + + + + maven-failsafe-plugin + + false + + + + + + native-image @@ -141,10 +178,10 @@ - mariadb + docker-mariadb - !no-mariadb + docker From 8f8c3a90b50489567c89b37d046a8214120c7dd9 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 22 Dec 2018 21:50:01 +0100 Subject: [PATCH 07/10] Disable testing with PostgreSQL by default You need to use -Dtest-postgresql to enable testing and -Ddocker to run the PostgreSQL server in a Docker container. --- examples/jpa-postgresql/pom.xml | 41 +++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/examples/jpa-postgresql/pom.xml b/examples/jpa-postgresql/pom.xml index a06b931969f95..42f6477b38b06 100644 --- a/examples/jpa-postgresql/pom.xml +++ b/examples/jpa-postgresql/pom.xml @@ -67,6 +67,18 @@ + + maven-surefire-plugin + + true + + + + maven-failsafe-plugin + + true + + ${project.groupId} shamrock-maven-plugin @@ -83,6 +95,31 @@ + + test-postgresql + + + test-postgresql + + + + + + maven-surefire-plugin + + false + + + + maven-failsafe-plugin + + false + + + + + + native-image @@ -140,10 +177,10 @@ - postgres + docker-postgresql - !no-postgres + docker From a5b96f5eb6091290dd2c53f50b6a2e50d9c55be7 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sat, 22 Dec 2018 21:50:27 +0100 Subject: [PATCH 08/10] Always enable building the jpa-mariadb example It's now the tests that are disabled by default. --- examples/pom.xml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index f4d7373150452..4118c475095b7 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -43,20 +43,7 @@ common-jpa-entities strict jpa-postgresql + jpa-mariadb jpa-h2 - - - - - - !mac - - - - - jpa-mariadb - - - From fe5f9abb86e15c8eb5835f4d434a08dc519dfd80 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Sun, 23 Dec 2018 14:39:00 +0100 Subject: [PATCH 09/10] Update CONTRIBUTING.md --- CONTRIBUTING.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a4e39279e970..2166673e4cef3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,7 +51,10 @@ If you have not done so on this machine, you need to: * macOS * `xcode-select --install` * Set `GRAALVM_HOME` to your GraalVM Home directory e.g. `/opt/graalvm` on Linux or `$location/JDK/GraalVM/Contents/Home` on macOS -* To build Shamrock, you also need Docker running. Check [the installation guide](https://docs.docker.com/install/), and [the MacOS installation guide](https://docs.docker.com/docker-for-mac/install/) + +Docker is not strictly necessary: it is used to run the MariaDB and PostgreSQL tests which are not enabled by default. However it is a recommended install if you plan to work on Shamrock JPA support: + +* Check [the installation guide](https://docs.docker.com/install/), and [the MacOS installation guide](https://docs.docker.com/docker-for-mac/install/) * If you just install docker, be sure that your current user can run a container (no root required). On Linux, check [the post-installation guide](https://docs.docker.com/install/linux/linux-postinstall/) From e45d6a2f0b9231b6fd8fa37d000f80d052ed6a47 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Thu, 27 Dec 2018 23:55:07 +0100 Subject: [PATCH 10/10] Add README.mds to the MariaDB and PostgreSQL examples --- examples/jpa-mariadb/README.md | 27 +++++++++++++++++++++++++++ examples/jpa-postgresql/README.md | 27 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 examples/jpa-mariadb/README.md create mode 100644 examples/jpa-postgresql/README.md diff --git a/examples/jpa-mariadb/README.md b/examples/jpa-mariadb/README.md new file mode 100644 index 0000000000000..7ec45c64b23fd --- /dev/null +++ b/examples/jpa-mariadb/README.md @@ -0,0 +1,27 @@ +# JPA example with MariaDB + +## Running the tests + +By default, the tests of this module are disabled. + +To run the tests in a standard JVM with MariaDB started as a Docker container, you can run the following command: + +``` +mvn clean install -Dtest-mariadb -Ddocker +``` + +Additionaly, you can generate a native image and run the tests for this native image by adding `-Dnative`: + +``` +mvn clean install -Dtest-mariadb -Ddocker -Dnative +``` + +If you don't want to run MariaDB as a Docker container, you can start your own MariaDB server. It needs to listen on the default port and have a database called `hibernate_orm_test` accessible to the user `hibernate_orm_test` with the password `hibernate_orm_test`. + +You can then run the tests as follows (either with `-Dnative` or not): + +``` +mvn clean install -Dtest-mariadb +``` + +If you have specific requirements, you can define a specific connection URL with `-Dmariadb.url=jdbc:mariadb://...`. diff --git a/examples/jpa-postgresql/README.md b/examples/jpa-postgresql/README.md new file mode 100644 index 0000000000000..cb9caa30181f6 --- /dev/null +++ b/examples/jpa-postgresql/README.md @@ -0,0 +1,27 @@ +# JPA example with PostgreSQL + +## Running the tests + +By default, the tests of this module are disabled. + +To run the tests in a standard JVM with PostgreSQL started as a Docker container, you can run the following command: + +``` +mvn clean install -Dtest-postgresql -Ddocker +``` + +Additionaly, you can generate a native image and run the tests for this native image by adding `-Dnative`: + +``` +mvn clean install -Dtest-postgresql -Ddocker -Dnative +``` + +If you don't want to run PostgreSQL as a Docker container, you can start your own PostgreSQL server. It needs to listen on the default port and have a database called `hibernate_orm_test` accessible to the user `hibernate_orm_test` with the password `hibernate_orm_test`. + +You can then run the tests as follows (either with `-Dnative` or not): + +``` +mvn clean install -Dtest-postgresql +``` + +If you have specific requirements, you can define a specific connection URL with `-Dpostgres.url=jdbc:postgresql://...`.