This is an automated email from the ASF dual-hosted git repository. bdelacretaz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlet-helpers.git
commit 126e48fbac86916081aa4d92225e92654c4ca5e3 Author: Bertrand Delacretaz <[email protected]> AuthorDate: Mon Jun 15 15:40:44 2020 +0200 SLING-9512 - add integration tests --- pom.xml | 105 ++++++++++++++++++- .../internalrequests/InternalRequest.java | 15 ++- .../internalrequests/ServletInternalRequest.java | 2 + .../internalrequests/SlingInternalRequest.java | 1 + .../internalrequests/RequestInfoServlet.java | 12 ++- .../it/ServletHelpersTestSupport.java | 116 +++++++++++++++++++++ .../it/ServletInternalRequestIT.java | 49 +++++++++ .../servlethelpers/it/SlingInternalRequestIT.java | 43 ++++++++ .../sling/servlethelpers/it/TestServlet.java | 46 ++++++++ src/test/resources/logback.xml | 32 ++++++ 10 files changed, 414 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 6da5b67..e992499 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>org.apache.sling</groupId> <artifactId>sling-bundle-parent</artifactId> - <version>35</version> + <version>38</version> <relativePath /> </parent> @@ -34,16 +34,26 @@ <name>Apache Sling Servlet Helpers</name> <description>Mock implementations of SlingHttpServletRequest, SlingHttpServletResponse and related classes.</description> + <properties> + <org.ops4j.pax.exam.version>4.13.3</org.ops4j.pax.exam.version> + <!-- To debug the pax process, override this with -D --> + <pax.vm.options>-Xmx512M</pax.vm.options> + </properties> + <scm> <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlet-helpers.git</connection> <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlet-helpers.git</developerConnection> <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-servlet-helpers.git</url> <tag>HEAD</tag> - </scm> + </scm> <build> <plugins> <plugin> + <groupId>org.apache.servicemix.tooling</groupId> + <artifactId>depends-maven-plugin</artifactId> + </plugin> + <plugin> <groupId>biz.aQute.bnd</groupId> <artifactId>bnd-maven-plugin</artifactId> </plugin> @@ -51,6 +61,39 @@ <groupId>biz.aQute.bnd</groupId> <artifactId>bnd-baseline-maven-plugin</artifactId> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <id>integration-test</id> + <phase>integration-test</phase> + <goals> + <goal>integration-test</goal> + </goals> + </execution> + <execution> + <id>verify</id> + <phase>integration-test</phase> + <goals> + <goal>verify</goal> + </goals> + </execution> + </executions> + <configuration> + <redirectTestOutputToFile>true</redirectTestOutputToFile> + <systemProperties> + <property> + <name>bundle.filename</name> + <value>${basedir}/target/${project.build.finalName}.jar</value> + </property> + <property> + <name>pax.vm.options</name> + <value>${pax.vm.options}</value> + </property> + </systemProperties> + </configuration> + </plugin> </plugins> </build> @@ -113,11 +156,69 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.osgi</groupId> + <artifactId>osgi.cmpn</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.service.component.annotations</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>3.1.0</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.ops4j.pax.exam</groupId> + <artifactId>pax-exam</artifactId> + <version>${org.ops4j.pax.exam.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.ops4j.pax.exam</groupId> + <artifactId>pax-exam-cm</artifactId> + <version>${org.ops4j.pax.exam.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.ops4j.pax.exam</groupId> + <artifactId>pax-exam-container-forked</artifactId> + <version>${org.ops4j.pax.exam.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.ops4j.pax.exam</groupId> + <artifactId>pax-exam-junit4</artifactId> + <version>${org.ops4j.pax.exam.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.ops4j.pax.exam</groupId> + <artifactId>pax-exam-link-mvn</artifactId> + <version>${org.ops4j.pax.exam.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-atinject_1.0_spec</artifactId> + <version>1.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.testing.paxexam</artifactId> + <version>3.1.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.framework</artifactId> + <version>6.0.3</version> + <scope>test</scope> + </dependency> </dependencies> diff --git a/src/main/java/org/apache/sling/servlethelpers/internalrequests/InternalRequest.java b/src/main/java/org/apache/sling/servlethelpers/internalrequests/InternalRequest.java index 8822e05..d1ca7e5 100644 --- a/src/main/java/org/apache/sling/servlethelpers/internalrequests/InternalRequest.java +++ b/src/main/java/org/apache/sling/servlethelpers/internalrequests/InternalRequest.java @@ -36,6 +36,7 @@ import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.servlethelpers.MockRequestPathInfo; import org.apache.sling.servlethelpers.MockSlingHttpServletRequest; import org.apache.sling.servlethelpers.MockSlingHttpServletResponse; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -72,11 +73,23 @@ public abstract class InternalRequest { public static final String MDC_KEY = "sling." + InternalRequest.class.getSimpleName(); /** Clients use subclasses of this one */ - protected InternalRequest(ResourceResolver resourceResolver, String path) { + protected InternalRequest(@NotNull ResourceResolver resourceResolver, @NotNull String path) { + checkNotNull(ResourceResolver.class, resourceResolver); + checkNotNull("path", path); this.resourceResolver = resourceResolver; this.path = path; } + protected void checkNotNull(String info, Object candidate) { + if(candidate == null) { + throw new IllegalArgumentException(info + " is null"); + } + } + + protected void checkNotNull(Class<?> clazz, Object candidate) { + checkNotNull(clazz.getSimpleName(), candidate); + } + /** Set the HTTP request method to use - defaults to GET */ public InternalRequest withRequestMethod(String method) { this.requestMethod = method.toUpperCase(); diff --git a/src/main/java/org/apache/sling/servlethelpers/internalrequests/ServletInternalRequest.java b/src/main/java/org/apache/sling/servlethelpers/internalrequests/ServletInternalRequest.java index f94764e..7c3bbf3 100644 --- a/src/main/java/org/apache/sling/servlethelpers/internalrequests/ServletInternalRequest.java +++ b/src/main/java/org/apache/sling/servlethelpers/internalrequests/ServletInternalRequest.java @@ -51,6 +51,8 @@ public class ServletInternalRequest extends InternalRequest { */ public ServletInternalRequest(@NotNull ServletResolver servletResolver, @NotNull Resource resource) { super(resource.getResourceResolver(), resource.getPath()); + checkNotNull(ServletResolver.class, servletResolver); + checkNotNull(Resource.class, resource); this.resource = resource; this.servletResolver = servletResolver; } diff --git a/src/main/java/org/apache/sling/servlethelpers/internalrequests/SlingInternalRequest.java b/src/main/java/org/apache/sling/servlethelpers/internalrequests/SlingInternalRequest.java index 7b2dc90..9057786 100644 --- a/src/main/java/org/apache/sling/servlethelpers/internalrequests/SlingInternalRequest.java +++ b/src/main/java/org/apache/sling/servlethelpers/internalrequests/SlingInternalRequest.java @@ -51,6 +51,7 @@ public class SlingInternalRequest extends InternalRequest { /** Setup an internal request that uses a SlingRequestProcessor */ public SlingInternalRequest(@NotNull ResourceResolver resourceResolver, @NotNull SlingRequestProcessor p, @NotNull String path) { super(resourceResolver, path); + checkNotNull(SlingRequestProcessor.class, p); this.processor = p; } diff --git a/src/test/java/org/apache/sling/servlethelpers/internalrequests/RequestInfoServlet.java b/src/test/java/org/apache/sling/servlethelpers/internalrequests/RequestInfoServlet.java index 2db8708..d3aba8b 100644 --- a/src/test/java/org/apache/sling/servlethelpers/internalrequests/RequestInfoServlet.java +++ b/src/test/java/org/apache/sling/servlethelpers/internalrequests/RequestInfoServlet.java @@ -18,6 +18,8 @@ */ package org.apache.sling.servlethelpers.internalrequests; +import static org.mockito.ArgumentMatchers.nullable; + import java.io.BufferedReader; import java.io.IOException; import java.util.Arrays; @@ -52,20 +54,22 @@ class RequestInfoServlet extends SlingAllMethodsServlet { sb.append(" RT_").append(resolutionRequest.getResource().getResourceType()); sb.append(" RST_").append(resolutionRequest.getResource().getResourceSuperType()); } - sb.append(" RRA_").append(resolutionRequest.getResource().getResourceResolver().getAttribute("testAttribute")); + if(resolutionRequest.getResource().getResourceResolver() != null) { + sb.append(" RRA_").append(resolutionRequest.getResource().getResourceResolver().getAttribute("testAttribute")); + } resolutionInfo = sb.toString(); } @Override public void service(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException,ServletException { - if(request.getResource().getPath().equals("/EXCEPTION")) { + if("/EXCEPTION".equals(request.getResource().getPath())) { throw new IOException("Failing as designed"); } - if(request.getResource().getPath().equals("/SERVLET-EXCEPTION")) { + if("/SERVLET-EXCEPTION".equals(request.getResource().getPath())) { throw new ServletException("Failing as designed"); } - if(request.getMethod().equals("STATUS")) { + if("STATUS".equals(request.getMethod())) { response.setContentType("farenheit"); response.sendError(451); return; diff --git a/src/test/java/org/apache/sling/servlethelpers/it/ServletHelpersTestSupport.java b/src/test/java/org/apache/sling/servlethelpers/it/ServletHelpersTestSupport.java new file mode 100644 index 0000000..e43963f --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/it/ServletHelpersTestSupport.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.sling.servlethelpers.it; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; +import org.apache.sling.engine.SlingRequestProcessor; +import org.apache.sling.servlethelpers.internalrequests.SlingInternalRequest; +import org.apache.sling.testing.paxexam.TestSupport; +import org.junit.Before; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; + +import static org.apache.sling.testing.paxexam.SlingOptions.slingQuickstartOakTar; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.apache.sling.testing.paxexam.SlingOptions.logback; +import static org.ops4j.pax.exam.CoreOptions.composite; +import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.vmOption; +import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +public abstract class ServletHelpersTestSupport extends TestSupport { + + private final static int STARTUP_WAIT_SECONDS = 30; + protected Resource rootResource; + protected ResourceResolver adminResourceResolver; + + @Inject + protected ResourceResolverFactory rrFactory; + + @Inject + protected SlingRequestProcessor slingRequestProcessor; + + @Configuration + public Option[] configuration() { + return options( + composite( + super.baseConfiguration(), + vmOption(System.getProperty("pax.vm.options")), + slingQuickstart(), + logback(), + junitBundles(), + testBundle("bundle.filename"), + buildBundleWithBnd(TestServlet.class), + newConfiguration("org.apache.sling.jcr.base.internal.LoginAdminWhitelist") + .put("whitelist.bundles.regexp", "^PAXEXAM.*$") + .asOption() + ) + ); + } + + @Before + public void setup() throws Exception { + adminResourceResolver = rrFactory.getAdministrativeResourceResolver(null); + rootResource = adminResourceResolver.getResource("/"); + assertNotNull("Expecting root resource", rootResource); + + // Wait for Sling to be ready + // detecting services would be more elegant...but this is very reliable + final Instant endTime = Instant.now().plus(Duration.ofSeconds(STARTUP_WAIT_SECONDS)); + final int expectedStatus = 200; + final String path ="/"; + final List<Integer> statuses = new ArrayList<>(); + boolean ok = false; + while(Instant.now().isBefore(endTime)) { + final int status = new SlingInternalRequest(adminResourceResolver, slingRequestProcessor, path) + .withExtension("json") + .execute() + .checkStatus() + .getStatus() + ; + statuses.add(status); + if(status == expectedStatus) { + ok = true; + break; + } + Thread.sleep(250); + } + + if(!ok) { + fail("Did not get a " + expectedStatus + " status at " + path + " got " + statuses); + } + } + + protected Option slingQuickstart() { + final String workingDirectory = workingDirectory(); + final int httpPort = findFreePort(); + return composite( + slingQuickstartOakTar(workingDirectory, httpPort) + ); + } +} diff --git a/src/test/java/org/apache/sling/servlethelpers/it/ServletInternalRequestIT.java b/src/test/java/org/apache/sling/servlethelpers/it/ServletInternalRequestIT.java new file mode 100644 index 0000000..6f52c0a --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/it/ServletInternalRequestIT.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.sling.servlethelpers.it; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import javax.inject.Inject; + +import org.apache.sling.api.servlets.ServletResolver; +import org.apache.sling.servlethelpers.internalrequests.ServletInternalRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class ServletInternalRequestIT extends ServletHelpersTestSupport { + @Inject + private ServletResolver servletResolver; + + @Test + public void testRequest() throws IOException { + final String content = new ServletInternalRequest(servletResolver, rootResource) + .withExtension("TestServlet") + .execute() + .checkStatus(200) + .getResponseAsString() + ; + assertEquals(TestServlet.class.getName(), content); + } +} diff --git a/src/test/java/org/apache/sling/servlethelpers/it/SlingInternalRequestIT.java b/src/test/java/org/apache/sling/servlethelpers/it/SlingInternalRequestIT.java new file mode 100644 index 0000000..de629fb --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/it/SlingInternalRequestIT.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.sling.servlethelpers.it; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.apache.sling.servlethelpers.internalrequests.SlingInternalRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class SlingInternalRequestIT extends ServletHelpersTestSupport { + @Test + public void testRequest() throws IOException { + final String content = new SlingInternalRequest(adminResourceResolver, slingRequestProcessor, "/") + .withExtension("TestServlet") + .execute() + .checkStatus(200) + .getResponseAsString() + ; + assertEquals(TestServlet.class.getName(), content); + } +} diff --git a/src/test/java/org/apache/sling/servlethelpers/it/TestServlet.java b/src/test/java/org/apache/sling/servlethelpers/it/TestServlet.java new file mode 100644 index 0000000..6b47d42 --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/it/TestServlet.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.sling.servlethelpers.it; + +import java.io.IOException; + +import javax.servlet.Servlet; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.osgi.service.component.annotations.Component; + +/** Not all servlets can be called directly from a {@link ServletInternalRequest}, + * depending on the environment that they expect, request attributes etc. + * + * This is a test one with zero environment requirements. + */ +@Component( + service=Servlet.class, + property = { + "sling.servlet.resourceTypes=sling/servlet/default", + "sling.servlet.extensions=TestServlet" + }) +public class TestServlet extends SlingAllMethodsServlet { + private static final long serialVersionUID = 1L; + + @Override + public void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { + response.getWriter().write(getClass().getName()); + } +} \ No newline at end of file diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml new file mode 100644 index 0000000..a603c15 --- /dev/null +++ b/src/test/resources/logback.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> +<configuration> + <appender name="file" class="ch.qos.logback.core.FileAppender"> + <file>target/test.log</file> + <append>true</append> + <encoder> + <pattern>%date level=%level thread=%thread logger=%logger sourcefile=%file line=%line %mdc message=%msg%n</pattern> + </encoder> + </appender> + + <root level="info"> + <appender-ref ref="file"/> + </root> +</configuration>
