blob: 830bddec27e1020fd04a8604bb7334cf4b474cac [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.test;
import java.io.InputStream;
import java.util.Properties;
import org.eclipse.gemini.blueprint.test.internal.util.IOUtils;
import org.eclipse.gemini.blueprint.test.internal.util.jar.JarCreator;
import org.osgi.framework.BundleContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
/**
* Abstract JUnit base class that allows easy OSGi integration testing. It
* builds on its super classes to allow full configuration of the underlying
* OSGi platform implementation, of the test bundle creation (including the
* manifest automatic generation).
* <p/>
* <p/>This class follows the <em>traditional</em> Spring style of integration
* testing in which the test simply indicates the dependencies, leaving the rest
* of the work to be done by its super classes. Consider the following simple
* example:
* <p/>
* <pre class="code">
* public class SimpleOsgiTest extends AbstractConfigurableBundleCreatorTests {
* <p/>
* public void testOsgiPlatformStarts() throws Exception {
* System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VENDOR));
* System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VERSION));
* System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT));
* }
* }
* </pre>
* <p/>
* <p/> The above class can be ran just like any other JUnit test. Equinox
* platform will be automatically started, the test will packed in an OSGi
* bundle (with its manifest created automatically) which will be deployed
* inside the OSGi platform. After running the test inside the OSGi environment,
* the test results (whether they are exceptions or failures) will be reported
* back to the running tool transparently. Please see the reference
* documentation for more examples, customization tips and help on how to do
* efficient and fast integration testing.
* <p/>
* <p/> This class allows the test on-the-fly bundle (jar) can be configured
* declarativelyā€ˇ by indicating the locations for:
* <ul>
* <li>root folder ({@value #ROOT_DIR}) - the starting point on which the
* resource patterns are applied</li>
* <li>inclusion patterns ({@value #INCLUDE_PATTERNS})- comma separated
* strings which identify the resources that should be included into the
* archive.</li>
* <li>manifest ({@value #MANIFEST})- the location of the manifest used for
* testing (if automatic generation is undesired).</li>
* </ul>
* <p/> These settings can be configured by:
* <ul>
* <li>using a properties file. By default the property name follows the
* pattern "[testName]-bundle.properties", (i.e. /foo/bar/SomeTest will try to
* load file /foo/bar/SomeTest-bundle.properties). If no properties file is
* found, a set of defaults will be used.</li>
* <p/>
* <li>overriding the default getXXX methods and providing an alternative
* implementation.</li>
* </ul>
* <p/>
* <p/>Another useful functionality inherited from
* {@link AbstractOnTheFlyBundleCreatorTests} class is the ability to create a
* manifest for the test bundle on the fly, based on the classes present in the
* archive.
* <p/>
* <p/><b>Note:</b> This class is the main testing framework entry point
*
* @author Costin Leau
* @see AbstractOnTheFlyBundleCreatorTests
*/
public abstract class AbstractConfigurableBundleCreatorTests extends AbstractOnTheFlyBundleCreatorTests {
protected static final String ROOT_DIR = "root.dir";
protected static final String INCLUDE_PATTERNS = "include.patterns";
protected static final String LIBS = "libs";
protected static final String MANIFEST = "manifest";
private static final Properties DEFAULT_SETTINGS = new Properties();
static {
DEFAULT_SETTINGS.setProperty(ROOT_DIR, Thread.currentThread().getContextClassLoader().getResource(".").toString());
DEFAULT_SETTINGS.setProperty(INCLUDE_PATTERNS, JarCreator.EVERYTHING_PATTERN);
DEFAULT_SETTINGS.setProperty(LIBS, "");
DEFAULT_SETTINGS.setProperty(MANIFEST, "");
}
/**
* Settings for the jar creation. Static as it has to be cached between test
* runs and it is being initialized once in
* {@link #postProcessBundleContext(BundleContext)}.
*/
private static Properties jarSettings;
protected String getRootPath() {
return jarSettings.getProperty(ROOT_DIR);
}
/**
* {@inheritDoc}
* <p/>
* <p/>Ant-style patterns for identifying the resources added to the jar.The
* patterns are considered from the root path when performing the search.
* <p/>
* <p/> By default, the content pattern is <code>*&#42;/*</code> which
* includes all sources from the root. One can configure the pattern to
* include specific files by using different patterns. For example, to
* include just the classes, XML and properties files one can use the
* following patterns:
* <ol>
* <li><code>*&#42;/*.class</code> for classes
* <li><code>*&#42;/*.xml</code> for XML files
* <li><code>*&#42;/*.properties</code> for properties files
* </ol>
*
* @return array of Ant-style pattern
*/
protected String[] getBundleContentPattern() {
return StringUtils.commaDelimitedListToStringArray(jarSettings.getProperty(INCLUDE_PATTERNS));
}
protected String getManifestLocation() {
return jarSettings.getProperty(MANIFEST);
}
/**
* Returns the settings location (by default, the test name; i.e.
* <code>foo.bar.SomeTest</code> will try to load
* <code>foo/bar/SomeTest-bundle.properties</code>).
*
* @return settings location for this test
*/
protected String getSettingsLocation() {
return getClass().getName().replace('.', '/') + "-bundle.properties";
}
/**
* Returns the default settings used when creating the jar, in case no
* customisations have been applied. Unless the base class is used as a
* testing framework, consider using a properties file for specifying
* specific properties for a test case.
*
* @return default settings for creating the jar
* @see #getSettingsLocation()
*/
protected Properties getDefaultSettings() {
return DEFAULT_SETTINGS;
}
/**
* Returns the settings used for creating this jar. This method tries to
* locate and load the settings from the location indicated by
* {@link #getSettingsLocation()}. If no file is found, the default
* settings will be used.
* <p/>
* <p/> A non-null properties object will always be returned.
*
* @return settings for creating the on the fly jar
* @throws Exception if loading the settings file fails
*/
protected Properties getSettings() throws Exception {
Properties settings = new Properties(getDefaultSettings());
// settings.setProperty(ROOT_DIR, getRootPath());
Resource resource = new ClassPathResource(getSettingsLocation());
if (resource.exists()) {
InputStream stream = resource.getInputStream();
try {
if (stream != null) {
settings.load(stream);
logger.debug("Loaded jar settings from " + getSettingsLocation());
}
} finally {
IOUtils.closeStream(stream);
}
} else {
logger.info(getSettingsLocation() + " was not found; using defaults");
}
return settings;
}
/*
* Loads the jar settings, first from the disk falling back to the default
* settings, if none is found.
*/
protected void postProcessBundleContext(BundleContext context) throws Exception {
// hook in properties loading
// reset the settings (useful when running multiple tests)
jarSettings = null;
// load settings
jarSettings = getSettings();
// Somehow the JarCreator needs to get this
jarCreator.setRootPath(getRootPath());
super.postProcessBundleContext(context);
}
}