You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2019/06/06 15:10:09 UTC
[sling-whiteboard] 11/16: Converted IntegrationTest to a proper IT
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
commit 9a46cacd3b36be0f692af79601c6a04e5f9eb1d5
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Wed Jun 5 17:00:17 2019 +0200
Converted IntegrationTest to a proper IT
- load the java agent from the compiled jar
- switch to using a surefire test
---
url-connection-agent/pom.xml | 12 ++
.../java/org/apache/sling/uca/impl/AgentIT.java | 163 +++++++++++++++++++++
.../org/apache/sling/uca/impl/IntegrationTest.java | 107 --------------
3 files changed, 175 insertions(+), 107 deletions(-)
diff --git a/url-connection-agent/pom.xml b/url-connection-agent/pom.xml
index bc5a25f..1e96414 100644
--- a/url-connection-agent/pom.xml
+++ b/url-connection-agent/pom.xml
@@ -57,6 +57,18 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
diff --git a/url-connection-agent/src/test/java/org/apache/sling/uca/impl/AgentIT.java b/url-connection-agent/src/test/java/org/apache/sling/uca/impl/AgentIT.java
new file mode 100644
index 0000000..b67a650
--- /dev/null
+++ b/url-connection-agent/src/test/java/org/apache/sling/uca/impl/AgentIT.java
@@ -0,0 +1,163 @@
+/*
+ * 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.uca.impl;
+
+import static java.time.Duration.ofSeconds;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTimeout;
+
+import java.io.IOException;
+import java.lang.ProcessBuilder.Redirect;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Validates that accessing URLs that exhibit connection problems results in a timeouts being fired when the agent is used
+ *
+ * <p>This test validates that the agent works when statically loaded, i.e. with a <tt>-javaagent:</tt> flag
+ * passed to the JVM. As such it requires launching a new JVM instance each time, otherwise the results are
+ * not valid.</p>
+ *
+ * <p>It does so by reusing the same JVM as the one running the test. Validation is done by looking for a
+ * Throwable information in the stderr and recording the exception class name and the message.</p>
+ *
+ */
+@ExtendWith(MisbehavingServerExtension.class)
+public class AgentIT {
+
+ private static final Path STDERR = Paths.get("target", "stderr.txt");
+ private static final Path STDOUT = Paths.get("target", "stdout.txt");
+ private static final Logger LOG = LoggerFactory.getLogger(AgentIT.class);
+
+ /**
+ * Validates that connecting to a unaccessible port on an existing port fails with a connect
+ * timeout exception
+ *
+ * <p>It is surprisingly hard to simulate a connnection timeout. The most reliable way seems to
+ * be to get a firewall to drop packets, but this is very hard to do portably and safely
+ * in a unit test. The least bad possible solution is to access an URL that we know will timeout
+ * and that is able to sustain additional traffic. Maven Central is a good candidate for that.</p>
+ *
+ * @throws IOException various I/O problems
+ */
+ @Test
+ public void connectTimeout() throws IOException {
+
+ RecordedThrowable error = assertTimeout(ofSeconds(5), () -> runTest("http://repo1.maven.org:81"));
+ assertEquals(SocketTimeoutException.class.getName(), error.className);
+ assertEquals("connect timed out", error.message);
+ }
+
+ /**
+ * Validates that connecting to a host that delays the response fails with a read timeout
+ *
+ * @throws IOException various I/O problems
+ */
+ @Test
+ public void readTimeout(MisbehavingServerControl server) throws IOException {
+
+ RecordedThrowable error = assertTimeout(ofSeconds(5), () -> runTest("http://localhost:" + server.getLocalPort()));
+ assertEquals(SocketTimeoutException.class.getName(), error.className);
+ assertEquals("Read timed out", error.message);
+ }
+
+
+ private RecordedThrowable runTest(String urlSpec) throws IOException, InterruptedException {
+
+ Process process = runForkedCommandWithAgent(new URL(urlSpec), 3, 3);
+ int exitCode = process.waitFor();
+
+ LOG.info("Exited with code {}", exitCode);
+ LOG.info("Dump of stdout: ");
+ Files
+ .lines(STDOUT)
+ .forEach(LOG::info);
+
+ LOG.info("Dump of stderr: ");
+ Files
+ .lines(STDERR)
+ .forEach(LOG::info);
+
+ if ( exitCode != 0 ) {
+ return Files.lines(STDERR)
+ .filter( l -> l.startsWith("Exception in thread \"main\""))
+ .map( l -> newRecordedThrowable(l) )
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException("Exit code was zero but did not find any exception information in stderr.txt"));
+ }
+
+ return null;
+ }
+
+ private Process runForkedCommandWithAgent(URL url, int connectTimeoutSeconds, int readTimeoutSeconds) throws IOException {
+
+ Path jar = Files.list(Paths.get("target"))
+ .filter( p -> p.getFileName().toString().endsWith("-jar-with-dependencies.jar"))
+ .findFirst()
+ .orElseThrow( () -> new IllegalStateException("Did not find the agent jar. Did you run mvn package first?"));
+
+ String javaHome = System.getProperty("java.home");
+ Path javaExe = Paths.get(javaHome, "bin", "java");
+ ProcessBuilder pb = new ProcessBuilder(
+ javaExe.toString(),
+ "-showversion",
+ "-javaagent:" + jar +"=" + TimeUnit.SECONDS.toMillis(connectTimeoutSeconds) +"," + TimeUnit.SECONDS.toMillis(readTimeoutSeconds),
+ "-cp",
+ jar.toString(),
+ "org.apache.sling.uca.impl.Main",
+ url.toString()
+ );
+
+ pb.redirectInput(Redirect.INHERIT);
+ pb.redirectOutput(STDOUT.toFile());
+ pb.redirectError(STDERR.toFile());
+
+ return pb.start();
+ }
+
+ private RecordedThrowable newRecordedThrowable(String string) {
+
+ string = string.replace("Exception in thread \"main\"", "");
+ String[] parts = string.split(":");
+
+ return new RecordedThrowable(parts[0].trim(), parts[1].trim());
+ }
+
+ /**
+ * Basic information about a {@link Throwable} that was recorded in a file
+ */
+ static class RecordedThrowable {
+ String className;
+ String message;
+
+ public RecordedThrowable(String className, String message) {
+ this.className = className;
+ this.message = message;
+ }
+
+
+ }
+}
diff --git a/url-connection-agent/src/test/java/org/apache/sling/uca/impl/IntegrationTest.java b/url-connection-agent/src/test/java/org/apache/sling/uca/impl/IntegrationTest.java
deleted file mode 100644
index 9e42394..0000000
--- a/url-connection-agent/src/test/java/org/apache/sling/uca/impl/IntegrationTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.uca.impl;
-
-import static java.time.Duration.ofSeconds;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTimeout;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@ExtendWith(MisbehavingServerExtension.class)
-public class IntegrationTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(IntegrationTest.class);
-
- /**
- * Validates that connecting to a unaccessible port on an existing port fails with a connect
- * timeout exception
- *
- * <p>It is surprisingly hard to simulate a connnection timeout. The most reliable way seems to
- * be to get a firewall to drop packets, but this is very hard to do portably and safely
- * in a unit test. The least bad possible solution is to access an URL that we know will timeout
- * and that is able to sustain additional traffic. Maven Central is a good candidate for that.</p>
- *
- * @throws IOException various I/O problems
- */
- @Test
- public void connectTimeout() throws IOException {
-
- SocketTimeoutException exception = assertThrows(SocketTimeoutException.class,
- () -> assertTimeout(ofSeconds(5), () -> runTest("http://repo1.maven.org:81"))
- );
- assertEquals("connect timed out", exception.getMessage());
- }
-
- /**
- * Validates that connecting to a host that delays the response fails with a read timeout
- *
- * @throws IOException various I/O problems
- */
- @Test
- public void readTimeout(MisbehavingServerControl server) throws IOException {
-
- SocketTimeoutException exception = assertThrows(SocketTimeoutException.class,
- () -> assertTimeout(ofSeconds(10), () -> runTest("http://localhost:" + server.getLocalPort()))
- );
- assertEquals("Read timed out", exception.getMessage());
- }
-
-
- private void runTest(String urlSpec) throws MalformedURLException, IOException, InterruptedException {
-
- String javaHome = System.getProperty("java.home");
- Path javaExe = Paths.get(javaHome, "bin", "java");
- ProcessBuilder pb = new ProcessBuilder(javaExe.toString(), "-version");
- pb.inheritIO();
- Process process = pb.start();
-
- process.getInputStream();
-
- int exitCode = process.waitFor();
-
- LOG.info("Exited with code {}", exitCode);
-
- URL url = new URL(urlSpec);
- LOG.info("connecting to {}", url);
- URLConnection connection = url.openConnection();
- // TODO - remove when running through the harness
- connection.setConnectTimeout((int) TimeUnit.SECONDS.toMillis(3));
- connection.setReadTimeout((int) TimeUnit.SECONDS.toMillis(3));
- connection.connect();
- LOG.info("connected");
- try ( InputStream is = connection.getInputStream()) {
- while ( is.read() != -1)
- ;
- }
- LOG.info("read");
- }
-}