junit
diff --git a/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/NodeMockUtils.java b/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/NodeMockUtils.java
index a12ff8f..a136a0b 100644
--- a/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/NodeMockUtils.java
+++ b/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/NodeMockUtils.java
@@ -410,7 +410,7 @@ public static Node mockPlainNode(final String name) throws RepositoryException {
when(result.setProperty(anyString(), any(Value.class), anyInt())).thenAnswer(SET_VALUE_PROPERTY_ANSWER);
when(result.setProperty(anyString(), any(Value[].class))).thenAnswer(SET_VALUES_PROPERTY_ANSWER);
when(result.setProperty(anyString(), any(Value[].class), anyInt())).thenAnswer(SET_VALUES_PROPERTY_ANSWER);
- doAnswer(Answers.CALLS_REAL_METHODS.get()).when(result).remove();
+ doAnswer(Answers.CALLS_REAL_METHODS).when(result).remove();
// check if this is the correct default value
stubType(NodeType.NT_BASE).of(result);
when(result.isNodeType(anyString())).then(IS_NODE_TYPE_ANSWER);
diff --git a/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/PropertyMockUtils.java b/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/PropertyMockUtils.java
index d538373..baf79b4 100644
--- a/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/PropertyMockUtils.java
+++ b/magkit-test-jcr/src/main/java/de/ibmix/magkit/test/jcr/PropertyMockUtils.java
@@ -120,7 +120,7 @@ public static Property mockProperty(final String name) throws RepositoryExceptio
when(property.getSession()).then(NodeMockUtils.SESSION_ANSWER);
when(property.getValues()).thenReturn(new Value[0]);
when(property.isMultiple()).then(IS_MULTIPLE_ANSWER);
- doAnswer(Answers.CALLS_REAL_METHODS.get()).when(property).remove();
+ doAnswer(Answers.CALLS_REAL_METHODS).when(property).remove();
PropertyStubbingOperation.stubAccept().of(property);
return property;
}
diff --git a/magkit-test-server/pom.xml b/magkit-test-server/pom.xml
new file mode 100644
index 0000000..90700df
--- /dev/null
+++ b/magkit-test-server/pom.xml
@@ -0,0 +1,73 @@
+
+
+ 4.0.0
+
+ de.ibmix.magkit
+ magkit-test
+ 1.0.7-SNAPSHOT
+ ../pom.xml
+
+
+ magkit-test-server
+ magkit-test-server Maven Module
+ jar
+
+
+ 9.0.74
+
+ ${project.basedir}/../magkit-test-webapp/target/site/jacoco-aggregate/jacoco.xml
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+
+
+ org.mockito
+ mockito-core
+
+
+ org.mockito
+ mockito-junit-jupiter
+
+
+ org.hamcrest
+ hamcrest
+ compile
+
+
+ io.rest-assured
+ rest-assured
+ ${restAssuredVersion}
+
+
+ org.apache.tomcat
+ tomcat-catalina
+ ${test.tomcat.version}
+
+
+ org.apache.tomcat
+ tomcat-util-scan
+ ${test.tomcat.version}
+
+
+ org.apache.tomcat
+ tomcat-jasper
+ ${test.tomcat.version}
+
+
+
+ info.magnolia
+ magnolia-core
+
+
+ info.magnolia.cache
+ magnolia-cache-core
+
+
+
+
diff --git a/magkit-test-server/src/main/java/de/ibmix/magkit/test/server/MagnoliaTomcatExtension.java b/magkit-test-server/src/main/java/de/ibmix/magkit/test/server/MagnoliaTomcatExtension.java
new file mode 100644
index 0000000..2101002
--- /dev/null
+++ b/magkit-test-server/src/main/java/de/ibmix/magkit/test/server/MagnoliaTomcatExtension.java
@@ -0,0 +1,210 @@
+package de.ibmix.magkit.test.server;
+
+/*-
+ * #%L
+ * magkit-test-server Maven Module
+ * %%
+ * Copyright (C) 2023 - 2024 IBM iX
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.groovy.parser.antlr4.util.StringUtils;
+import org.apache.tomcat.util.scan.StandardJarScanner;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+import io.restassured.config.HttpClientConfig;
+import io.restassured.internal.RequestSpecificationImpl;
+import io.restassured.specification.RequestSpecification;
+
+/**
+ * Starts up Tomcat with a given Magnolia webapp. This allows to execute tests
+ * that verify requests using RestAssured and at the same time inspect Magnolia
+ * configuration inside the running Tomcat, in order to test e.g. custom
+ * {@link info.magnolia.module.delta.Task}s.
+ *
+ * The example webapp POM in magkit-testwebapp shows how to run it using "mvn
+ * integration-test -DtomcatTest". Test must be run using special
+ * maven-surefire-plugin configuration, please see pom.xml of the example
+ * magkit-test-webapp.
+ *
+ * Expects the WAR file or folder name given as system property
+ * {@link MagnoliaTomcatExtension#WAR_NAME_SYSTEM_PROPERTY}, or as argument to
+ * {@link Builder#setWarName(String)}, and expects that file or folder to exist
+ * in the "target" folder of the current directory.
+ *
+ * @author joerg.frantzius
+ */
+public class MagnoliaTomcatExtension implements BeforeAllCallback, AfterAllCallback {
+
+ public static final String WAR_NAME_SYSTEM_PROPERTY = "project.build.finalName";
+ public static final String LOCAL_AUTHOR_URL = "http://127.0.0.1:8080";
+
+ // system property that tells us to set RestAssured request timeouts to
+ // unlimited,
+ // so tests can be debugged
+ public static final String NO_TEST_REQUEST_TIMEOUT_SYSTEM_PROPERTY = "de.ibmix.magkit.test.server.noTestRequestTimeout";
+
+ private static final String MAGNOLIA_AUTOUPDATE_CONFIG_PROP = "magnolia.update.auto";
+ private static final String MAGNOLIA_JACKRABBIT_CONFIG_PROP = "magnolia.repositories.jackrabbit.config";
+ private static final String MAGNOLIA_LOGS_DIR_CONFIG_PROP = "magnolia.logs.dir";
+ private static final String MAGNOLIA_REPOSITORIES_HOME_CONFIG_PROP = "magnolia.repositories.home";
+
+ private final Tomcat _tomcat = new Tomcat();
+ private StandardContext _webAppContext;
+ private String _warName = System.getProperty(WAR_NAME_SYSTEM_PROPERTY);
+
+ /**
+ * Use this instead of RestAssured.given() in order to be able to debug
+ * RestAssured tests without timeout, by setting system property
+ * {@link #NO_TEST_REQUEST_TIMEOUT_SYSTEM_PROPERTY}.
+ */
+ public static RequestSpecification given() {
+ RequestSpecification given = io.restassured.RestAssured.given();
+ // conditionally set request timeout to unlimited to allow for debugging
+ if (Boolean.getBoolean(NO_TEST_REQUEST_TIMEOUT_SYSTEM_PROPERTY)) {
+ // if you find a less hacky way of setting the timeout, please apply it,
+ // https://stackoverflow.com/a/46913204 simply didn't work for me
+ HttpClientConfig noTimeoutConfig = HttpClientConfig.httpClientConfig().setParam("http.socket.timeout", 0);
+ ((RequestSpecificationImpl) given).applyHttpClientConfig(noTimeoutConfig);
+ }
+ return given;
+ }
+
+ /**
+ * Configure Magnolia for proper logging and with H2 in-memory DB.
+ *
+ * @throws IOException
+ */
+ private void configureMagnolia() throws IOException {
+ Path currentDir = Paths.get("").toAbsolutePath();
+ Path magnoliaDir = currentDir.resolve("target/magnolia");
+
+ // must override log directory
+ Path magnoliaLogsDir = magnoliaDir.resolve("logs");
+ Files.createDirectories(magnoliaLogsDir);
+ System.setProperty(MAGNOLIA_LOGS_DIR_CONFIG_PROP, magnoliaDir.toString());
+
+ // must override repositories directory
+ Path magnoliaRepositoriesDir = magnoliaDir.resolve("repositories");
+ Files.createDirectories(magnoliaRepositoriesDir);
+ System.setProperty(MAGNOLIA_REPOSITORIES_HOME_CONFIG_PROP, magnoliaRepositoriesDir.toString());
+
+ // use in-memory H2 DB, config comes with magnolia-dx-core-webapp overlay
+ System.setProperty(MAGNOLIA_JACKRABBIT_CONFIG_PROP, "WEB-INF/config/repo-conf/jackrabbit-memory-search.xml");
+
+ // let Magnolia start up without waiting for user input
+ System.setProperty(MAGNOLIA_AUTOUPDATE_CONFIG_PROP, "true");
+ }
+
+ @Override
+ public void beforeAll(ExtensionContext context) throws IOException, LifecycleException {
+ if (StringUtils.isEmpty(_warName)) {
+ throw new RuntimeException(
+ "TomcatTest expectation failed: given warName is empty, and system property project.build.finalName is also empty, please configure maven-surefire-plugin to pass this as a system property as shown here: https://maven.apache.org/surefire/maven-surefire-plugin/examples/system-properties.html");
+ }
+ configureMagnolia();
+
+ // create a new directory for Tomcat
+ Path currentDir = Paths.get("").toAbsolutePath();
+ Path tomcatDir = currentDir.resolve("target/TomcatTest");
+ Files.createDirectories(tomcatDir);
+
+ _tomcat.setPort(8080);
+ _tomcat.setBaseDir("./target/TomcatTest");
+ _tomcat.getHost().setAutoDeploy(true);
+ Path webAppDir = currentDir.resolve("target/" + _warName);
+ _webAppContext = (StandardContext) _tomcat.addWebapp("", webAppDir.toFile().getAbsolutePath());
+ // prevent Tomcat from scanning for web fragments in the JVM classpath (i.e. not
+ // in the web app classpath),
+ // as StandardJarScanner.processManifest() otherwise produces bogus classpath
+ // entries for non-existant
+ // JARs found in the manifest of vaadin-server
+ ((StandardJarScanner) _webAppContext.getJarScanner()).setScanClassPath(false);
+ // make Tomcat use the Surefire classloader, or we get ClassCastExceptions
+ // because Magnolia classes
+ // loaded by our test use the Surefire classloader, while Magnolia in the webapp
+ // uses the
+ // Tomcat webapp classloader
+ _webAppContext.setParentClassLoader(MagnoliaTomcatExtension.class.getClassLoader());
+ _webAppContext.setDelegate(true);
+
+ _tomcat.init();
+ // must call getConnector(), see https://stackoverflow.com/a/59282431/1245428
+ _tomcat.getConnector();
+ _tomcat.start();
+
+ // run server loop that waits for shutdown command
+ CompletableFuture.supplyAsync(() -> {
+ _tomcat.getServer().await();
+ return true;
+ });
+ }
+
+ @Override
+ public void afterAll(ExtensionContext context) throws Exception {
+ _tomcat.stop();
+ }
+
+ public String getServerUrl() {
+ return LOCAL_AUTHOR_URL;
+ }
+
+ /**
+ * Provides Builder pattern as in
+ * https://github.com/junit-team/junit5/blob/main/documentation/src/main/java/example/registration/WebServerExtension.java
+ * .
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String _warName;
+
+ /**
+ * Set the name of the WAR file / folder to be deployed, which is expected to
+ * exist within the "target" folder of the current directory. If it is not set
+ * here, {@link MagnoliaTomcatExtension} expects a system propery
+ */
+ public Builder setWarName(String warNameArg) {
+ if (StringUtils.isEmpty(warNameArg)) {
+ throw new IllegalArgumentException("warName must not be empty");
+ }
+ _warName = warNameArg;
+ return this;
+ }
+
+ public MagnoliaTomcatExtension build() {
+ MagnoliaTomcatExtension tomcatExtension = new MagnoliaTomcatExtension();
+ if (_warName != null) {
+ tomcatExtension._warName = _warName;
+ }
+ return tomcatExtension;
+ }
+
+ }
+
+}
diff --git a/magkit-test-servlet/pom.xml b/magkit-test-servlet/pom.xml
index caa851f..f22869e 100644
--- a/magkit-test-servlet/pom.xml
+++ b/magkit-test-servlet/pom.xml
@@ -5,7 +5,7 @@
de.ibmix.magkit
magkit-test
- 1.0.6-SNAPSHOT
+ 1.0.7-SNAPSHOT
../pom.xml
@@ -14,6 +14,11 @@
Utility classes to easily mock javax.servlet classes.
jar
+
+
+ ${project.basedir}/../magkit-test-webapp/target/site/jacoco-aggregate/jacoco.xml
+
+
junit
@@ -35,7 +40,7 @@
org.hamcrest
- hamcrest-core
+ hamcrest
compile
diff --git a/magkit-test-webapp/pom.xml b/magkit-test-webapp/pom.xml
new file mode 100644
index 0000000..abe6797
--- /dev/null
+++ b/magkit-test-webapp/pom.xml
@@ -0,0 +1,185 @@
+
+
+ 4.0.0
+
+ de.ibmix.magkit
+ magkit-test
+ 1.0.7-SNAPSHOT
+ ../pom.xml
+
+
+ magkit-test-webapp
+ magkit-test-webapp Magnolia Webapp that runs a TomcatTest
+ jar
+
+
+
+ info.magnolia.bundle
+ magnolia-community-webapp
+ war
+
+
+ info.magnolia.bundle
+ magnolia-community-webapp
+ pom
+
+
+
+ info.magnolia.groovy
+ magnolia-groovy
+
+
+
+
+
+ magkit-test-server
+ de.ibmix.magkit
+ ${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
+
+ default-war
+ none
+
+
+ war-exploded
+ package
+
+ exploded
+
+
+
+
+
+ WEB-INF/lib/*.jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+
+ true
+
+
+
+ unit-tests
+ test
+
+ test
+
+
+
+ false
+
+
+ **/*Tomcat*Test.java
+
+
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ report
+
+ report-aggregate
+
+ verify
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+
+ true
+
+
+
+
+
+
+
+
+
+
+ tomcatTest
+
+
+ tomcatTest
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-tests
+ integration-test
+
+ test
+
+
+
+ false
+
+
+ **/*Tomcat*Test.java
+
+
+
+ ${project.build.finalName}
+
+
+ @{argLine}
+
+--add-opens=java.base/java.lang=ALL-UNNAMED
+--add-opens=java.base/java.io=ALL-UNNAMED
+--add-opens=java.base/java.util=ALL-UNNAMED
+--add-opens=java.base/java.util.concurrent=ALL-UNNAMED
+--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
+
+
+
+
+
+
+
+
+
+
+
diff --git a/magkit-test-webapp/src/test/java/de/ibmix/magkit/test/webapp/TomcatExtensionTest.java b/magkit-test-webapp/src/test/java/de/ibmix/magkit/test/webapp/TomcatExtensionTest.java
new file mode 100644
index 0000000..634cbe7
--- /dev/null
+++ b/magkit-test-webapp/src/test/java/de/ibmix/magkit/test/webapp/TomcatExtensionTest.java
@@ -0,0 +1,78 @@
+
+package de.ibmix.magkit.test.webapp;
+/*-
+ * #%L
+ * magkit-test-webapp Magnolia Webapp that runs a TomcatTest
+ * %%
+ * Copyright (C) 2023 - 2024 IBM iX
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+
+import static io.restassured.RestAssured.get;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import de.ibmix.magkit.test.server.MagnoliaTomcatExtension;
+import info.magnolia.module.cache.CacheModule;
+import info.magnolia.module.cache.cachepolicy.Default;
+import info.magnolia.objectfactory.Components;
+import io.restassured.response.Response;
+
+/**
+ * Example test for using {@link MagnoliaTomcatExtension}, with one test using
+ * RestAssured requests against running Magnolia, and another showing how to
+ * query and test Magnolia configuration registry within the same JVM.
+ * @author joerg.frantzius
+ */
+@ExtendWith(MagnoliaTomcatExtension.class)
+public class TomcatExtensionTest {
+
+ /**
+ * Example of a test using RestAssured against Magnolia running in Tomcat:
+ * verify that local Magnolia superuser can login.
+ */
+ @Test
+ public void testLocalSuperuserLogin() throws Exception {
+ Response response = get(MagnoliaTomcatExtension.LOCAL_AUTHOR_URL + "/.magnolia/admincentral");
+ assertEquals(401, response.getStatusCode());
+ String csrfCookie = response.getCookie("csrf");
+ assertNotNull(csrfCookie);
+
+ loginLocalSuperuser(MagnoliaTomcatExtension.LOCAL_AUTHOR_URL, csrfCookie).then().statusCode(302);
+ }
+
+ private Response loginLocalSuperuser(String address, String csrfCookie) {
+ return MagnoliaTomcatExtension.given().cookie("csrf", csrfCookie)
+ .formParams(Map.of("mgnlUserId", "superuser", "mgnlUserPSWD", "superuser", "csrf", csrfCookie)).when()
+ .post(address + "/.magnolia/admincentral");
+ }
+
+ /**
+ * Example of a test that accesses the running Magnolia's object registry to
+ * verify some configuration is as expected, e.g. as written by some UpdateTask
+ */
+ @Test
+ public void testMagnoliaConfig() {
+ CacheModule cacheModule = Components.getComponent(CacheModule.class);
+ Default cachePolicy = (Default) cacheModule.getContentCaching("defaultPageCache").getCachePolicy();
+ assertNotNull(cachePolicy, "Expected defaultPageCache config to exist!");
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 19ea28a..8c81be3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,5 +1,7 @@
-
+
4.0.0
de.ibmix.magkit
@@ -7,7 +9,7 @@
1.0.6
magkit-test
- 1.0.6-SNAPSHOT
+ 1.0.7-SNAPSHOT
pom
magkit-test Magnolia Module
@@ -17,18 +19,31 @@
magkit-test-jcr
magkit-test-servlet
magkit-test-cms
+ magkit-test-server
+ magkit-test-webapp
- 1.3
+ 2.2
2.2.5
+ 5.10.2
+ 5.12.0
+
+ 1.14.15
+ 5.4.0
+
+ 6.2.45
+ 0.8.12
+
+ 3.3.0
org.hamcrest
- hamcrest-core
+ hamcrest
${version.hamcrest-core}
test
@@ -40,9 +55,109 @@
${version.el-api}
provided
+
+