SLING-837 copy JCR Install testcases to the launchpad/testing module
and include them in the jcrinstall-tests profile
git-svn-id: https://svn.apache.org/repos/asf/incubator/sling/trunk@736674 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 18a85fe..8b32e6f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,6 +80,33 @@
started. Useful to manually test the integration testing webapp.
-->
<integration.test.wait>false</integration.test.wait>
+
+ <!--
+ Defines the part of the tree, which must not be compiled in
+ normal test scenarios. The jcrinstall-tests profile will
+ compile these classes to be included in a full-test scenario.
+ -->
+ <jcrinstall.integration.test.code.path>
+ **/jcrinstall/**
+ </jcrinstall.integration.test.code.path>
+
+ <!--
+ Where to copy our test bundles
+ Used when profile jcrinstall-tests is active
+ -->
+ <sling.testbundles.path>${project.build.directory}/testbundles</sling.testbundles.path>
+
+ <!--
+ Can be used to run tests with more or less bundles
+ Used when profile jcrinstall-tests is active
+ -->
+ <sling.test.scale.factor>1</sling.test.scale.factor>
+
+ <!--
+ How long to wait for the expected number of bundles to be active, in tests
+ Used when profile jcrinstall-tests is active
+ -->
+ <sling.test.bundles.wait.seconds>20</sling.test.bundles.wait.seconds>
</properties>
<build>
@@ -214,6 +241,25 @@
</executions>
</plugin>
+ <!--
+ Exclude the JCRInstall test classes from default build
+ See jcrinstall-tests for the setup of compilation of these
+ classes for a full test
+ -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <sumpf>gurk</sumpf>
+ <testExcludes>
+ <testExclude>
+ ${jcrinstall.integration.test.code.path}
+ </testExclude>
+ </testExcludes>
+ <verbose>true</verbose>
+ </configuration>
+ </plugin>
+
<!--
Include sling-app launcher classes and resources, but no Sling
bundles (we want to specify our own versions)
@@ -353,6 +399,20 @@
http://${test.host}:${http.port}/${project.build.finalName}/${webdav.workspace.path}
</value>
</property>
+
+ <!-- system properties used for profile jcrinstall-tests -->
+ <property>
+ <name>sling.testbundles.path</name>
+ <value>${sling.testbundles.path}</value>
+ </property>
+ <property>
+ <name>sling.test.scale.factor</name>
+ <value>${sling.test.scale.factor}</value>
+ </property>
+ <property>
+ <name>sling.test.bundles.wait.seconds</name>
+ <value>${sling.test.bundles.wait.seconds}</value>
+ </property>
</systemProperties>
</configuration>
</execution>
@@ -432,6 +492,96 @@
</plugins>
</build>
</profile>
+
+ <!--
+ The jcrinstall-tests profile includes the integration tests
+ for the JCRInstall functionality in the integration tests. By
+ default this profile is disabled.
+ For CI builds it is recommended to activate this profile, for
+ normal builds you may omit this profile
+ -->
+ <profile>
+ <id>jcrinstall-tests</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-jcrinstall-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>
+ ${project.build.directory}/launchpad-bundles/resources/0
+ </outputDirectory>
+ <excludeTransitive>true</excludeTransitive>
+ <includeArtifactIds>
+ org.apache.sling.jcr.jcrinstall,org.apache.sling.jcr.jcrinstall.testbundles.observer,org.apache.sling.jcr.jcrinstall.servlet,org.apache.sling.runmode
+ </includeArtifactIds>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>compile-jcrinstall-tests</id>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ <configuration>
+ <testIncludes>
+ <testInclude>
+ ${jcrinstall.integration.test.code.path}
+ </testInclude>
+ </testIncludes>
+ <!-- overwrite global setting here -->
+ <testExcludes>
+ <testExclude>
+ dummymarker
+ </testExclude>
+ </testExcludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.jcr.jcrinstall</artifactId>
+ <version>2.0.3-incubator-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.jcr.jcrinstall.testbundles.observer</artifactId>
+ <version>2.0.3-incubator-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.jcr.jcrinstall.servlet</artifactId>
+ <version>2.0.3-incubator-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.runmode</artifactId>
+ <version>2.0.3-incubator-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ </profile>
</profiles>
<dependencies>
@@ -463,6 +613,19 @@
<scope>provided</scope>
</dependency>
+ <!-- JCR Install - needs to be in a profile -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>biz.aQute</groupId>
+ <artifactId>bnd</artifactId>
+ <version>0.0.169</version>
+ <scope>test</scope>
+ </dependency>
+
<!-- Dependencies for the Test Build and Run -->
<dependency>
<groupId>org.apache.sling</groupId>
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/HttpPingTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/HttpPingTest.java
new file mode 100644
index 0000000..e1586da
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/HttpPingTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.launchpad.webapp.integrationtest.jcrinstall;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+
+/** Ping the Sling server to verify that our integration test
+ * setup is ok.
+ */
+public class HttpPingTest extends JcrinstallTestBase {
+
+ public void testWebServerRoot() throws Exception
+ {
+ final String url = HTTP_BASE_URL + "/";
+ assertHttpStatus(url, 403, "Root should return 403 as no redirect is setup in the repository");
+ }
+
+ public void test404() throws Exception
+ {
+ assertHttpStatus(HTTP_BASE_URL + "/someNonExistentUrl", 404);
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/InstallClonedBundlesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/InstallClonedBundlesTest.java
new file mode 100644
index 0000000..1e53fe4
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/InstallClonedBundlesTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.launchpad.webapp.integrationtest.jcrinstall;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/** Try installing some cloned bundles */
+public class InstallClonedBundlesTest extends JcrinstallTestBase {
+
+ public void testInstallAndRemoveBundles() throws Exception {
+ final int activeBeforeTest = getActiveBundlesCount();
+ final List<String> installed = new LinkedList<String>();
+
+ final int nBundles = 10 * scaleFactor;
+ for(int i=0 ; i < nBundles; i++) {
+ installed.add(installClonedBundle(null, null));
+ }
+
+ assertActiveBundleCount("after adding bundles",
+ activeBeforeTest + nBundles, defaultBundlesTimeout);
+
+ for(String path : installed) {
+ removeClonedBundle(path);
+ }
+
+ assertActiveBundleCount("after removing added bundles",
+ activeBeforeTest, defaultBundlesTimeout);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/JcrinstallTestBase.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/JcrinstallTestBase.java
new file mode 100644
index 0000000..6fde418
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/JcrinstallTestBase.java
@@ -0,0 +1,220 @@
+/*
+ * 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.launchpad.webapp.integrationtest.jcrinstall;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+import org.apache.sling.launchpad.webapp.integrationtest.jcrinstall.util.BundleCloner;
+import org.osgi.framework.Bundle;
+
+/** Base class for jcrinstall test cases */
+public class JcrinstallTestBase extends HttpTestBase {
+
+ public static final String JCRINSTALL_STATUS_PATH = "/system/sling/jcrinstall";
+ public static final String DEFAULT_INSTALL_PATH = "/libs/integration-testing/install";
+ public static final String DEFAULT_BUNDLE_NAME_PATTERN = "observer";
+ private static long bundleCounter = System.currentTimeMillis();
+ private static Set<String> installedClones;
+ public static final String SCALE_FACTOR_PROP = "sling.test.scale.factor";
+ public static final String DEFAULT_TIMEOUT_PROP = "sling.test.bundles.wait.seconds";
+ protected int scaleFactor;
+ protected int defaultBundlesTimeout;
+
+ private class ShutdownThread extends Thread {
+ @Override
+ public void run() {
+ try {
+ System.out.println("Deleting " + installedClones.size() + " cloned bundles...");
+ for(String path : installedClones) {
+ testClient.delete(WEBDAV_BASE_URL + path);
+ }
+ } catch(Exception e) {
+ System.out.println("Exception in ShutdownThread:" + e);
+ }
+ }
+
+ };
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ scaleFactor = requireIntProperty(SCALE_FACTOR_PROP);
+ defaultBundlesTimeout = requireIntProperty(DEFAULT_TIMEOUT_PROP);
+ enableJcrinstallService(true);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // TODO Auto-generated method stub
+ super.tearDown();
+ enableJcrinstallService(true);
+ }
+
+
+
+ protected int requireIntProperty(String systemPropertyKey) throws Exception {
+ final String s = System.getProperty(systemPropertyKey);
+ if(s == null) {
+ throw new Exception("Missing system property '" + systemPropertyKey + "'");
+ }
+ return Integer.valueOf(s);
+ }
+
+ /** Fail test if active bundles count is not expectedCount, after
+ * at most timeoutSeconds */
+ protected void assertActiveBundleCount(String message, int expectedCount, int timeoutSeconds) throws IOException {
+ final long start = System.currentTimeMillis();
+ final long timeout = start + timeoutSeconds * 1000L;
+ int count = 0;
+ int lastCount = -1;
+ while(System.currentTimeMillis() < timeout) {
+ count = getActiveBundlesCount();
+ if(count != lastCount) {
+ // continue until the count is stable for at least one second
+ lastCount = count;
+ sleep(1000);
+ continue;
+ } else if(count == expectedCount) {
+ return;
+ }
+ sleep(500);
+ }
+ final long delta = System.currentTimeMillis() - start;
+ fail(message + ": expected " + expectedCount + " active bundles, found " + count
+ + " after waiting " + delta / 1000.0 + " seconds");
+ }
+
+ protected void sleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch(InterruptedException ignore) {
+ }
+ }
+
+ protected int getActiveBundlesCount() throws IOException {
+ final String key = "bundles.in.state." + Bundle.ACTIVE;
+ final Properties props = getJcrInstallProperties();
+ int result = 0;
+ if(props.containsKey(key)) {
+ result = Integer.valueOf(props.getProperty(key));
+ }
+ return result;
+ }
+
+ protected boolean getJcrinstallServiceEnabled() throws IOException {
+ final Properties props = getJcrInstallProperties();
+ return "true".equals(props.get("jcrinstall.enabled"));
+ }
+
+ protected void enableJcrinstallService(boolean enable) throws IOException {
+ if(enable != getJcrinstallServiceEnabled()) {
+ final PostMethod post = new PostMethod(HTTP_BASE_URL + JCRINSTALL_STATUS_PATH);
+ post.setFollowRedirects(false);
+ post.addParameter("enabled", String.valueOf(enable));
+ final int status = httpClient.executeMethod(post);
+ assertEquals("Expected status 200 in enableJcrinstallService", 200, status);
+ assertEquals("Expected jcrinstall.enabled to be " + enable, enable, getJcrinstallServiceEnabled());
+ }
+ }
+
+ /** Return the Properties found at /system/sling/jcrinstall */
+ protected Properties getJcrInstallProperties() throws IOException {
+ final String content = getContent(HTTP_BASE_URL + JCRINSTALL_STATUS_PATH, CONTENT_TYPE_PLAIN);
+ final Properties result = new Properties();
+ result.load(new ByteArrayInputStream(content.getBytes("UTF-8")));
+ return result;
+ }
+
+ /** Remove a cloned bundle that had been installed before */
+ protected void removeClonedBundle(String path) throws IOException {
+ testClient.delete(WEBDAV_BASE_URL + path);
+ installedClones.remove(path);
+ }
+
+ /** Generate a clone of one of our test bundles, with unique bundle name and
+ * symbolic name, and install it via WebDAV.
+ * @param bundleNamePattern The first test bundle that contains this pattern
+ * is used as a source. If null, uses DEFAULT_BUNDLE_NAME_PATTERN
+ * @param installPath if null, use DEFAULT_INSTALL_PATH
+ * @return the path of the installed bundle
+ */
+ protected String installClonedBundle(String bundleNamePattern, String installPath) throws Exception {
+ if(bundleNamePattern == null) {
+ bundleNamePattern = DEFAULT_BUNDLE_NAME_PATTERN;
+ }
+ if(installPath == null) {
+ installPath = DEFAULT_INSTALL_PATH;
+ }
+
+ // find test bundle to clone
+ final File testBundlesDir = new File(System.getProperty("sling.testbundles.path"));
+ if(!testBundlesDir.isDirectory()) {
+ throw new IOException(testBundlesDir.getAbsolutePath() + " is not a directory");
+ }
+ File bundleSrc = null;
+ for(String bundle : testBundlesDir.list()) {
+ if(bundle.contains(bundleNamePattern)) {
+ bundleSrc = new File(testBundlesDir, bundle);
+ break;
+ }
+ }
+
+ // clone bundle
+ final File outputDir = new File(testBundlesDir, "cloned-bundles");
+ outputDir.mkdirs();
+ final String bundleId = bundleNamePattern + "_clone_" + bundleCounter++;
+ final File clone = new File(outputDir, bundleId + ".jar");
+ new BundleCloner().cloneBundle(bundleSrc, clone, bundleId, bundleId);
+
+ // install clone by copying to repository - jcrinstall should then pick it up
+ FileInputStream fis = new FileInputStream(clone);
+ final String path = installPath + "/" + clone.getName();
+ final String url = WEBDAV_BASE_URL + path;
+ try {
+ testClient.mkdirs(WEBDAV_BASE_URL, installPath);
+ testClient.upload(url, fis);
+ setupBundlesCleanup();
+ installedClones.add(path);
+ } finally {
+ if(fis != null) {
+ fis.close();
+ }
+ }
+
+ return path;
+ }
+
+ /** If not done yet, register a shutdown hook to delete cloned bundles that
+ * we installed.
+ */
+ private void setupBundlesCleanup() {
+ synchronized (JcrinstallTestBase.class) {
+ if(installedClones == null) {
+ installedClones = new HashSet<String>();
+ Runtime.getRuntime().addShutdownHook(new ShutdownThread());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/StopAndChangeBundlesTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/StopAndChangeBundlesTest.java
new file mode 100644
index 0000000..235e0ce
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/StopAndChangeBundlesTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.launchpad.webapp.integrationtest.jcrinstall;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/** Test replacing bundles while jcrinstall is disabled
+ */
+public class StopAndChangeBundlesTest extends JcrinstallTestBase {
+
+ public void testStopAndRestart() throws Exception {
+ final int activeBeforeTest = getActiveBundlesCount();
+ final List<String> installed = new LinkedList<String>();
+
+ final int nBundlesA = 7 * scaleFactor;
+ final int nBundlesB = 13 * scaleFactor;
+
+ assertActiveBundleCount("before adding bundles",
+ activeBeforeTest, defaultBundlesTimeout);
+
+ // Add a first set of bundles A
+ for(int i=0 ; i < nBundlesA; i++) {
+ installed.add(installClonedBundle(null, null));
+ }
+
+ // And check that they all start
+ assertActiveBundleCount("after adding bundles",
+ activeBeforeTest + nBundlesA, defaultBundlesTimeout);
+
+ // Disable jcrinstall (to simulate repository going away),
+ // delete set A and add another set of bundles B
+ enableJcrinstallService(false);
+
+ for(String path : installed) {
+ removeClonedBundle(path);
+ }
+ installed.clear();
+
+ for(int i=0 ; i < nBundlesB; i++) {
+ installed.add(installClonedBundle(null, null));
+ }
+
+ // Before reactivating, bundles count must be the initial count,
+ // as jcrinstall brings the start level down
+ assertActiveBundleCount("after replacing bundles",
+ activeBeforeTest, defaultBundlesTimeout);
+
+ // Re-enable and verify that only original bundles + set B are active
+ enableJcrinstallService(true);
+ assertActiveBundleCount("after re-enabling jcrinstall",
+ activeBeforeTest + nBundlesB, defaultBundlesTimeout);
+
+ // Remove everything and check
+ for(String path : installed) {
+ removeClonedBundle(path);
+ }
+
+ assertActiveBundleCount("after removing all added bundles",
+ activeBeforeTest, defaultBundlesTimeout);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/StopAndRestartTest.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/StopAndRestartTest.java
new file mode 100644
index 0000000..bf3041a
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/StopAndRestartTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.launchpad.webapp.integrationtest.jcrinstall;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/** Verify that stopping and restarting jcrinstall (simulating a disappearing
+ * repository) works as expected.
+ */
+public class StopAndRestartTest extends JcrinstallTestBase {
+
+ public void testStopAndRestart() throws Exception {
+ final int activeBeforeTest = getActiveBundlesCount();
+ final List<String> installed = new LinkedList<String>();
+
+ final int nBundles = 10 * scaleFactor;
+ for(int i=0 ; i < nBundles; i++) {
+ installed.add(installClonedBundle(null, null));
+ }
+
+ assertActiveBundleCount("after adding bundles",
+ activeBeforeTest + nBundles, defaultBundlesTimeout);
+
+ enableJcrinstallService(false);
+
+ assertActiveBundleCount("after disabling jcrinstall",
+ activeBeforeTest, defaultBundlesTimeout);
+
+ enableJcrinstallService(true);
+
+ assertActiveBundleCount("after re-enabling jcrinstall",
+ activeBeforeTest + nBundles, defaultBundlesTimeout);
+
+ for(String path : installed) {
+ removeClonedBundle(path);
+ }
+
+ assertActiveBundleCount("after removing added bundles",
+ activeBeforeTest, defaultBundlesTimeout);
+ }
+}
diff --git a/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/util/BundleCloner.java b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/util/BundleCloner.java
new file mode 100644
index 0000000..3a68d8c
--- /dev/null
+++ b/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/jcrinstall/util/BundleCloner.java
@@ -0,0 +1,55 @@
+/*
+ * 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.launchpad.webapp.integrationtest.jcrinstall.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import aQute.bnd.main.bnd;
+
+/** Generate a clone of an OSGi bundle, with its
+ * own Bundle-Name and Bundle-SymbolicName.
+ */
+public class BundleCloner {
+ private final bnd bnd = new bnd();
+
+ /** Create a clone of supplied bundle */
+ public void cloneBundle(File bundle, File output, String name, String symbolicName) throws Exception {
+ int options = 0;
+
+ Properties props = new Properties();
+ props.put("Bundle-Name", name);
+ props.put("Bundle-SymbolicName", symbolicName);
+ File properties = File.createTempFile(getClass().getSimpleName(), "properties");
+ final OutputStream out = new FileOutputStream(properties);
+
+ File classpath[] = null;
+ try {
+ props.store(out, getClass().getSimpleName());
+ bnd.doWrap(properties, bundle, output, classpath, options, null);
+ } finally {
+ if(out != null) {
+ out.close();
+ }
+ if(properties != null) {
+ properties.delete();
+ }
+ }
+ }
+}