Author: kwin
Date: Thu Feb 23 08:46:15 2017
New Revision: 1784090
URL: http://svn.apache.org/viewvc?rev=1784090&view=rev
Log:
SLING-6546, optionally enable logging, persist test-bundles and prevent test
bundle from being uninstalled
Modified:
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/ClientSideTeleporter.java
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DefaultPropertyBasedCustomizer.java
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DependencyAnalyzer.java
Modified:
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/ClientSideTeleporter.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/ClientSideTeleporter.java?rev=1784090&r1=1784089&r2=1784090&view=diff
==============================================================================
---
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/ClientSideTeleporter.java
(original)
+++
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/ClientSideTeleporter.java
Thu Feb 23 08:46:15 2017
@@ -18,8 +18,13 @@ package org.apache.sling.testing.telepor
import static org.junit.Assert.fail;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Collection;
@@ -30,12 +35,16 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import org.apache.commons.io.IOUtils;
import org.apache.sling.junit.rules.TeleporterRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.ops4j.pax.tinybundles.core.TinyBundle;
import org.ops4j.pax.tinybundles.core.TinyBundles;
import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.helpers.NOPLogger;
/** Client-side TeleporterRule. Packages the
* test to run in a test bundle, installs the bundle,
@@ -49,12 +58,17 @@ public class ClientSideTeleporter extend
private int testReadyTimeoutSeconds = 20;
private int webConsoleReadyTimeoutSeconds = 30;
private int waitForServiceTimout = 10;
+ private boolean enableLogging = false;
+ private boolean preventToUninstallBundle = false;
+ private File directoryForPersistingTestBundles = null;
private String baseUrl;
private String serverCredentials;
private String testServletPath = DEFAULT_TEST_SERVLET_PATH;
private final Set<Class<?>> embeddedClasses = new HashSet<Class<?>>();
private final Map<String, String> additionalBundleHeaders = new
HashMap<String, String>();
+ private Logger log;
+
private InputStream buildTestBundle(Class<?> c, Collection<Class<?>>
embeddedClasses, String bundleSymbolicName) throws IOException {
final TinyBundle b = TinyBundles.bundle()
.set(Constants.BUNDLE_SYMBOLICNAME, bundleSymbolicName)
@@ -66,6 +80,12 @@ public class ClientSideTeleporter extend
b.set(header.getKey(), header.getValue());
}
+ // enrich embedded classes by automatically detected dependencies
+ for(Class<?> embeddedClazz : dependencyAnalyzer.getDependencies(log)) {
+ log.info("Embed class '{}' because it is referenced and in the
allowed package prefixes", embeddedClazz);
+ embeddedClasses.add(embeddedClazz);
+ }
+
// Embed specified classes
for(Class<?> clz : embeddedClasses) {
b.add(clz);
@@ -78,6 +98,7 @@ public class ClientSideTeleporter extend
@Override
public void process(String resourcePath, InputStream
resourceStream) throws IOException {
b.add(resourcePath, resourceStream);
+ log.info("Embedded resource '{}' in test bundle",
resourcePath);
}
};
@@ -165,19 +186,56 @@ public class ClientSideTeleporter extend
public Map<String, String> getAdditionalBundleHeaders() {
return additionalBundleHeaders;
}
-
+
+ public void setEnableLogging(boolean enableLogging) {
+ this.enableLogging = enableLogging;
+ }
+
+ public void setPreventToUninstallBundle(boolean
preventToUninstallTestBundle) {
+ this.preventToUninstallBundle = preventToUninstallTestBundle;
+ }
+
+ public void setDirectoryForPersistingTestBundles(File
directoryForPersistingTestBundles) {
+ this.directoryForPersistingTestBundles =
directoryForPersistingTestBundles;
+ }
+
private String installTestBundle(TeleporterHttpClient httpClient) throws
MalformedURLException, IOException {
- final SimpleDateFormat fmt = new SimpleDateFormat("HH-mm-ss-");
- final String bundleSymbolicName = getClass().getSimpleName() + "." +
fmt.format(new Date()) + "." + UUID.randomUUID();
- final InputStream bundle = buildTestBundle(classUnderTest,
embeddedClasses, bundleSymbolicName);
- httpClient.installBundle(bundle, bundleSymbolicName,
webConsoleReadyTimeoutSeconds);
+ final SimpleDateFormat fmt = new SimpleDateFormat("HH-mm-ss");
+ final String bundleSymbolicName = getClass().getSimpleName() + "." +
classUnderTest.getSimpleName() + "." + fmt.format(new Date()) + "." +
UUID.randomUUID();
+ log.info("Installing bundle '{}' to {}", bundleSymbolicName, baseUrl);
+
+ try (final InputStream bundle = buildTestBundle(classUnderTest,
embeddedClasses, bundleSymbolicName)) {
+ // optionally persist the test bundle
+ if (directoryForPersistingTestBundles != null) {
+ directoryForPersistingTestBundles.mkdirs();
+ File bundleFile = new File(directoryForPersistingTestBundles,
bundleSymbolicName + ".jar");
+ log.info("Persisting test bundle in '{}'", bundleFile);
+ try (OutputStream output = new FileOutputStream(bundleFile)) {
+ IOUtils.copy(bundle, output);
+ }
+ try (InputStream bundleInput = new BufferedInputStream(new
FileInputStream(bundleFile))) {
+ httpClient.installBundle(bundleInput, bundleSymbolicName,
webConsoleReadyTimeoutSeconds);
+ }
+ } else {
+ httpClient.installBundle(bundle, bundleSymbolicName,
webConsoleReadyTimeoutSeconds);
+ }
+ httpClient.verifyCorrectBundleState(bundleSymbolicName,
webConsoleReadyTimeoutSeconds);
+ };
return bundleSymbolicName;
}
-
+
+ private void initLogger() {
+ if (enableLogging) {
+ log = LoggerFactory.getLogger(ClientSideTeleporter.class);
+ } else {
+ log = NOPLogger.NOP_LOGGER;
+ }
+ }
+
@Override
public Statement apply(final Statement base, final Description
description) {
customize();
-
+ initLogger();
if(baseUrl == null) {
fail("base URL is not set");
}
@@ -189,10 +247,6 @@ public class ClientSideTeleporter extend
if(baseUrl.endsWith("/")) {
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
}
-
- for(Class<?> c : dependencyAnalyzer.getDependencies()) {
- embeddedClasses.add(c);
- }
final TeleporterHttpClient httpClient = new
TeleporterHttpClient(baseUrl, testServletPath);
httpClient.setCredentials(serverCredentials);
@@ -204,12 +258,18 @@ public class ClientSideTeleporter extend
return new Statement() {
@Override
public void evaluate() throws Throwable {
+
final String bundleSymbolicName =
installTestBundle(httpClient);
final String testPath = description.getClassName() + "/" +
description.getMethodName();
try {
httpClient.runTests(testPath, testReadyTimeoutSeconds);
} finally {
- httpClient.uninstallBundle(bundleSymbolicName,
webConsoleReadyTimeoutSeconds);
+ if (!preventToUninstallBundle) {
+ log.info("Uninstalling bundle '{}' from {}",
bundleSymbolicName, baseUrl);
+ httpClient.uninstallBundle(bundleSymbolicName,
webConsoleReadyTimeoutSeconds);
+ } else {
+ log.info("Not uninstalling bundle '{}' from {} due to
according configuration", bundleSymbolicName, baseUrl);
+ }
}
}
};
Modified:
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DefaultPropertyBasedCustomizer.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DefaultPropertyBasedCustomizer.java?rev=1784090&r1=1784089&r2=1784090&view=diff
==============================================================================
---
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DefaultPropertyBasedCustomizer.java
(original)
+++
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DefaultPropertyBasedCustomizer.java
Thu Feb 23 08:46:15 2017
@@ -18,6 +18,8 @@ package org.apache.sling.testing.telepor
import static org.junit.Assert.fail;
+import java.io.File;
+
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.junit.rules.TeleporterRule;
import org.apache.sling.junit.rules.TeleporterRule.Customizer;
@@ -43,9 +45,15 @@ import org.apache.sling.junit.rules.Tele
* <li>{@code ClientSideTeleporter.excludeDependencyPrefixes},
comma-separated list of package prefixes for classes referenced from the IT.
* Classes having one of the given package prefix will not be included in
the bundle being deployed to the given Sling instance together with the IT
class itself.
* This takes precedence over the {@code
ClientSideTeleporter.includeDependencyPrefixes}.</li>
+ * <li>{@code ClientSideTeleporter.embedClasses}, comma-separated list of
fully qualified class names which should be embedded in the test bundle.
+ * Use this only for classes which are not detected automatically by the
Maven Dependency Analyzer but still should be embedded in the test bundle</li>
* <li>{@code ClientSideTeleporter.testReadyTimeoutSeconds}, how long to
wait for our test to be ready on the server-side in seconds, after installing
the test bundle. By default {@code 12}.</li>
* <li>{@code ClientSideTeleporter.serverUsername}, the username with
which to send requests to the Sling server. By default {@code admin}.</li>
* <li>{@code ClientSideTeleporter.serverPassword}, the password with
which to send requests to the Sling server. By default {@code admin}.</li>
+ * <li>{@code ClientSideTeleporter.enableLogging}, set to true to log the
tasks being performed by the teleporter. Useful for debugging.</li>
+ * <li>{@code ClientSideTeleporter.preventToUninstallBundle}, set to true
to not automatically uninstall the test bundle after test execution. Useful for
debugging.</li>
+ * <li>{@code ClientSideTeleporter.testBundleDirectory}, if set the test
bundles are being persisted (before being installed) within the given directory
name.
+ * If the directory does not exist, it will be automatically created.
Useful for debugging.</li>
* </ul>
*/
public class DefaultPropertyBasedCustomizer implements Customizer {
@@ -56,6 +64,9 @@ public class DefaultPropertyBasedCustomi
static final String PROPERTY_SERVER_PASSWORD =
"ClientSideTeleporter.serverPassword";
static final String PROPERTY_SERVER_USERNAME =
"ClientSideTeleporter.serverUsername";
static final String PROPERTY_TESTREADY_TIMEOUT_SECONDS =
"ClientSideTeleporter.testReadyTimeoutSeconds";
+ static final String PROPERTY_TESTBUNDLE_DIRECTORY =
"ClientSideTeleporter.testBundleDirectory";
+ static final String PROPERTY_ENABLE_LOGGING =
"ClientSideTeleporter.enableLogging";
+ static final String PROPERTY_PREVENT_TO_UNINSTALL_BUNDLE =
"ClientSideTeleporter.preventToUninstallBundle";
static final String LIST_SEPARATOR = ",";
@@ -66,6 +77,9 @@ public class DefaultPropertyBasedCustomi
private final String excludeDependencyPrefixes;
private final String embedClasses;
private final String baseUrl;
+ private final String testBundleDirectory;
+ private final boolean enableLogging;
+ private final boolean preventToUninstallBundle;
public DefaultPropertyBasedCustomizer() {
testReadyTimeout =
Integer.getInteger(PROPERTY_TESTREADY_TIMEOUT_SECONDS, 12);
@@ -75,6 +89,9 @@ public class DefaultPropertyBasedCustomi
excludeDependencyPrefixes =
System.getProperty(PROPERTY_EXCLUDE_DEPENDENCY_PREFIXES);
embedClasses = System.getProperty(PROPERTY_EMBED_CLASSES);
baseUrl = System.getProperty(PROPERTY_BASE_URL);
+ testBundleDirectory =
System.getProperty(PROPERTY_TESTBUNDLE_DIRECTORY);
+ enableLogging = Boolean.getBoolean(PROPERTY_ENABLE_LOGGING);
+ preventToUninstallBundle =
Boolean.getBoolean(PROPERTY_PREVENT_TO_UNINSTALL_BUNDLE);
}
@Override
@@ -83,6 +100,11 @@ public class DefaultPropertyBasedCustomi
if (StringUtils.isBlank(baseUrl)) {
fail("The mandatory system property " + PROPERTY_BASE_URL + " is
not set!");
}
+ cst.setEnableLogging(enableLogging);
+ cst.setPreventToUninstallBundle(preventToUninstallBundle);
+ if (StringUtils.isNotBlank(testBundleDirectory)) {
+ cst.setDirectoryForPersistingTestBundles(new
File(testBundleDirectory));
+ }
cst.setBaseUrl(baseUrl);
cst.setServerCredentials(serverUsername, serverPassword);
cst.setTestReadyTimeoutSeconds(testReadyTimeout);
Modified:
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DependencyAnalyzer.java
URL:
http://svn.apache.org/viewvc/sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DependencyAnalyzer.java?rev=1784090&r1=1784089&r2=1784090&view=diff
==============================================================================
---
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DependencyAnalyzer.java
(original)
+++
sling/trunk/testing/junit/teleporter/src/main/java/org/apache/sling/testing/teleporter/client/DependencyAnalyzer.java
Thu Feb 23 08:46:15 2017
@@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.Set;
import
org.apache.maven.shared.dependency.analyzer.asm.DependencyClassFileVisitor;
+import org.slf4j.Logger;
/** Find the class dependencies of a class, recursively,
* using the maven-dependency-analyzer and optionally considering only
@@ -62,13 +63,13 @@ class DependencyAnalyzer {
/** Get the aggregate dependencies of our classes, based on a recursive
* analysis that takes our include/exclude prefixes into account
*/
- synchronized Collection<Class<?>> getDependencies() {
+ synchronized Collection<Class<?>> getDependencies(Logger log) {
if(dependencies != null) {
return dependencies;
}
dependencies = new HashSet<Class<?>>();
for(Class<?> c : classes) {
- analyze(c);
+ analyze(c, log);
}
for(String dep : dependencyNames) {
dependencies.add(toClass(dep));
@@ -77,7 +78,7 @@ class DependencyAnalyzer {
}
/** Analyze a single class, recursively */
- private void analyze(Class<?> c) {
+ private void analyze(Class<?> c, Logger log) {
if(alreadySeen.contains(c)) {
return;
}
@@ -105,15 +106,15 @@ class DependencyAnalyzer {
if(dep.equals(c.getName())) {
continue;
}
- if(accept(dep)) {
+ if(accept(dep, log)) {
dependencyNames.add(dep);
- analyze(toClass(dep));
+ analyze(toClass(dep), log);
}
}
}
/** True if given class name matches our include/exclude prefixes */
- private boolean accept(String className) {
+ private boolean accept(String className, Logger log) {
boolean result = false;
for(String s : includes) {
@@ -128,10 +129,16 @@ class DependencyAnalyzer {
for(String s : excludes) {
if(className.startsWith(s)) {
result = false;
+ log.trace("Dependent class '{}' not included because
package blacklisted via exclude '{}'.", className, s);
break;
}
}
}
+ if (result) {
+ log.trace("Dependent class '{}' included because package not
whitelisted via include.", className);
+ } else {
+ log.trace("Dependent class '{}' not included because package not
whitelisted via include.", className);
+ }
return result;
}