Author: bdelacretaz Date: Thu Sep 10 14:38:56 2009 New Revision: 813460 URL: http://svn.apache.org/viewvc?rev=813460&view=rev Log: SLING-1078 - BundleInstallStressTest added
Added: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleInstallStressTest.java (with props) Modified: sling/trunk/installer/osgi/it/pom.xml sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java Modified: sling/trunk/installer/osgi/it/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/pom.xml?rev=813460&r1=813459&r2=813460&view=diff ============================================================================== --- sling/trunk/installer/osgi/it/pom.xml (original) +++ sling/trunk/installer/osgi/it/pom.xml Thu Sep 10 14:38:56 2009 @@ -37,6 +37,13 @@ <pax.exam.log.level>INFO</pax.exam.log.level> <!-- This can be set to activate remote debugging of the Pax Exam tests --> <pax.exam.debug.port></pax.exam.debug.port> + + <!-- BundleInstallStressTest parameters --> + <BundleInstallStressTest.default.bundles.folder>${project.build.directory}/bundle-install-stress-test-bundles</BundleInstallStressTest.default.bundles.folder> + <osgi.installer.BundleInstallStressTest.bundles.folder>${BundleInstallStressTest.default.bundles.folder}</osgi.installer.BundleInstallStressTest.bundles.folder> + <osgi.installer.BundleInstallStressTest.cycle.count>10</osgi.installer.BundleInstallStressTest.cycle.count> + <osgi.installer.BundleInstallStressTest.expect.timeout.seconds>30</osgi.installer.BundleInstallStressTest.expect.timeout.seconds> + </properties> <scm> @@ -89,6 +96,18 @@ <name>osgi.installer.base.dir</name> <value>${project.build.directory}</value> </property> + <property> + <name>osgi.installer.BundleInstallStressTest.bundles.folder</name> + <value>${osgi.installer.BundleInstallStressTest.bundles.folder}</value> + </property> + <property> + <name>osgi.installer.BundleInstallStressTest.cycle.count</name> + <value>${osgi.installer.BundleInstallStressTest.cycle.count}</value> + </property> + <property> + <name>osgi.installer.BundleInstallStressTest.expect.timeout.seconds</name> + <value>${osgi.installer.BundleInstallStressTest.expect.timeout.seconds}</value> + </property> </systemProperties> </configuration> </plugin> @@ -273,6 +292,31 @@ </execution> </executions> </plugin> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <phase>test-compile</phase> + <configuration> + <tasks> + <!-- Copy a set of distinct valid bundles for the BundleInstallStressTest --> + <mkdir dir="${BundleInstallStressTest.default.bundles.folder}"/> + <copy todir="${BundleInstallStressTest.default.bundles.folder}"> + <fileset dir="${project.build.directory}"> + <include name="*testbundle-1.2.jar"/> + <include name="*testB-1.0.jar"/> + <include name="*testA-1.0.jar"/> + <include name="*needsB.jar"/> + </fileset> + </copy> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> Added: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleInstallStressTest.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleInstallStressTest.java?rev=813460&view=auto ============================================================================== --- sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleInstallStressTest.java (added) +++ sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleInstallStressTest.java Thu Sep 10 14:38:56 2009 @@ -0,0 +1,206 @@ +/* + * 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.osgi.installer.it; + +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +import org.apache.sling.osgi.installer.InstallableResource; +import org.apache.sling.osgi.installer.OsgiInstaller; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.JUnit4TestRunner; +import org.osgi.framework.Bundle; +import org.osgi.service.log.LogService; + +/** Repeatedly install/remove/reinstall semi-random sets + * of bundles, to stress-test the installer and framework. + */ +...@runwith(JUnit4TestRunner.class) +public class BundleInstallStressTest extends OsgiInstallerTestBase { + + public static final String PROP_BUNDLES_FOLDER = "osgi.installer.BundleInstallStressTest.bundles.folder"; + public static final String PROP_CYCLE_COUNT = "osgi.installer.BundleInstallStressTest.cycle.count"; + public static final String PROP_EXPECT_TIMEOUT_SECONDS = "osgi.installer.BundleInstallStressTest.expect.timeout.seconds"; + public static final int MIN_TEST_BUNDLES = 4; + + /** Folder where test bundles are found */ + private File bundlesFolder; + + /** How many cycles to run */ + private int cycleCount; + + /** List of available test bundles */ + private List<File> testBundles; + + /** Always use the same random sequence */ + private Random random; + + /** Timeout for expectBundles() */ + private long expectBundlesTimeoutMsec; + + @org.ops4j.pax.exam.junit.Configuration + public static Option[] configuration() { + return defaultConfiguration(); + } + + @Before + public void setUp() { + setupInstaller(); + + final String bf = System.getProperty(PROP_BUNDLES_FOLDER); + if(bf == null) { + fail("Missing system property: " + PROP_BUNDLES_FOLDER); + } + bundlesFolder = new File(bf); + if(!bundlesFolder.isDirectory()) { + fail("Bundles folder '" + bundlesFolder.getAbsolutePath() + "' not found"); + } + + final String cc = System.getProperty(PROP_CYCLE_COUNT); + if(cc == null) { + fail("Missing system property:" + PROP_CYCLE_COUNT); + } + cycleCount = Integer.parseInt(cc); + + final String et = System.getProperty(PROP_EXPECT_TIMEOUT_SECONDS); + if(et == null) { + fail("Missing system property:" + PROP_EXPECT_TIMEOUT_SECONDS); + } + expectBundlesTimeoutMsec = Integer.parseInt(et) * 1000L; + + log(LogService.LOG_INFO, getClass().getSimpleName() + + ": cycle count=" + cycleCount + + ", expect timeout (msec)=" + expectBundlesTimeoutMsec + + ", test bundles folder=" + bundlesFolder.getAbsolutePath()); + + testBundles = new LinkedList<File>(); + final String [] files = bundlesFolder.list(); + for(String filename : files) { + if(filename.endsWith(".jar")) { + testBundles.add(new File(bundlesFolder, filename)); + } + } + + if(testBundles.size() < MIN_TEST_BUNDLES) { + fail("Found only " + testBundles.size() + + " bundles in test folder, expected at least " + MIN_TEST_BUNDLES + + " (test folder=" + bundlesFolder.getAbsolutePath() + ")" + ); + } + + random = new Random(42 + cycleCount); + } + + @After + public void tearDown() { + super.tearDown(); + } + + @Test + public void testSemiRandomInstall() throws Exception { + if(cycleCount < 1) { + fail("Cycle count (" + cycleCount + ") should be >= 1"); + } + + final int initialBundleCount = bundleContext.getBundles().length; + log(LogService.LOG_INFO,"Initial bundle count=" + initialBundleCount); + + // Start by installing all bundles + log(LogService.LOG_INFO,"Registering all test bundles, " + testBundles.size() + " resources"); + install(testBundles); + waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1); + expectBundleCount("After installing all test bundles", initialBundleCount + testBundles.size()); + + for(int i=0; i < cycleCount; i++) { + final long start = System.currentTimeMillis(); + log(LogService.LOG_DEBUG, "Test cycle " + i + ", semi-randomly selecting a subset of our test bundles"); + final List<File> toInstall = selectRandomBundles(); + log(LogService.LOG_INFO,"Re-registering " + toInstall.size() + " randomly selected resources (other test bundles should be uninstalled)"); + install(toInstall); + waitForInstallerAction(OsgiInstaller.WORKER_THREAD_BECOMES_IDLE_COUNTER, 1); + // TODO this sleep shouldn't be needed, probably hides a bug in OsgiInstallerImpl + sleep(2500L); + expectBundleCount("At cycle " + i, initialBundleCount + toInstall.size()); + log(LogService.LOG_INFO,"Test cycle " + i + " successful, " + + toInstall.size() + " bundles, " + + (System.currentTimeMillis() - start) + " msec"); + } + } + + private void install(List<File> bundles) throws IOException { + final List<InstallableResource> toInstall = new LinkedList<InstallableResource>(); + for(File f : bundles) { + toInstall.add(getInstallableResource(f, f.getAbsolutePath() + f.lastModified())); + } + installer.registerResources(toInstall, URL_SCHEME); + } + + private void expectBundleCount(String info, final int nBundles) throws Exception { + log(LogService.LOG_INFO,"Expecting " + nBundles + " bundles to be installed"); + final Condition c = new Condition() { + int actualCount = 0; + public boolean isTrue() throws Exception { + actualCount = bundleContext.getBundles().length; + return actualCount == nBundles; + } + + @Override + String additionalInfo() { + return "Expected " + nBundles + " installed bundles, got " + actualCount; + } + + @Override + void onFailure() { + log(LogService.LOG_INFO, "Failure: " + additionalInfo()); + for(Bundle b : bundleContext.getBundles()) { + log(LogService.LOG_INFO, "Installed bundle: " + b.getSymbolicName()); + } + } + + @Override + long getMsecBetweenEvaluations() { + return 1000L; + } + }; + waitForCondition(info, expectBundlesTimeoutMsec, c); + } + + private List<File> selectRandomBundles() { + final List<File> result = new LinkedList<File>(); + for(File f : testBundles) { + if(random.nextBoolean()) { + log(LogService.LOG_DEBUG, "Test bundle selected: " + f.getName()); + result.add(f); + } + } + + if(result.size() == 0) { + result.add(testBundles.get(0)); + } + + return result; + } +} Propchange: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleInstallStressTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/BundleInstallStressTest.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL Modified: sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java?rev=813460&r1=813459&r2=813460&view=diff ============================================================================== --- sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java (original) +++ sling/trunk/installer/osgi/it/src/test/java/org/apache/sling/osgi/installer/it/OsgiInstallerTestBase.java Thu Sep 10 14:38:56 2009 @@ -46,6 +46,7 @@ import org.osgi.framework.ServiceReference; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.log.LogService; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.util.tracker.ServiceTracker; @@ -65,8 +66,11 @@ public static final String URL_SCHEME = "OsgiInstallerTest"; - static interface Condition { - boolean isTrue() throws Exception; + static abstract class Condition { + abstract boolean isTrue() throws Exception; + String additionalInfo() { return null; } + void onFailure() { } + long getMsecBetweenEvaluations() { return 100L; } } @SuppressWarnings("unchecked") @@ -163,8 +167,14 @@ if(c.isTrue()) { return; } - Thread.sleep(100L); + Thread.sleep(c.getMsecBetweenEvaluations()); } while(System.currentTimeMillis() < end); + + if(c.additionalInfo() != null) { + info += " " + c.additionalInfo(); + } + + c.onFailure(); fail("WaitForCondition failed: " + info); } @@ -357,6 +367,11 @@ assertEquals("Expected value matches for counter " + index, value, installer.getCounters()[index]); } + protected void log(int level, String msg) { + final LogService log = getService(LogService.class); + log.log(LogService.LOG_INFO, msg); + } + public static Option[] defaultConfiguration() { String vmOpt = "-Dosgi.installer.testing";