blob: 9599974c487a9245799839dca11e284c00962ce0 [file] [log] [blame]
/*
* 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.felix.ipojo.junit4osgi;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.PackageAdmin;
/**
* OSGi Test Case.
* Allows the injection of the bundle context.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class OSGiTestCase extends TestCase {
/**
* The bundle context.
*/
protected BundleContext context;
/**
* List of get references.
*/
private List m_references = new ArrayList();
/**
* List of helpers.
*/
private List m_helpers = new ArrayList();
/**
* Gets the Bundle Context.
* @return the bundle context.
*/
public BundleContext getContext() {
return context;
}
/**
* Add an helper.
* This method is called by the {@link Helper#Helper(OSGiTestCase)}
* method.
* @param helper the helper object.
*/
public void addHelper(Helper helper) {
m_helpers.add(helper);
}
/**
* Extends runBare to release (unget) services after the teardown.
* @throws Throwable when an error occurs.
* @see junit.framework.TestCase#runBare()
*/
public void runBare() throws Throwable {
setUp();
try {
runTest();
} finally {
tearDown();
// Stop Helpers
for (int i = 0; i < m_helpers.size(); i++) {
((Helper) m_helpers.get(i)).dispose();
}
// Unget services
for (int i = 0; i < m_references.size(); i++) {
context.ungetService((ServiceReference) m_references.get(i));
}
m_references.clear();
}
}
public void setBundleContext(BundleContext bc) {
context = bc;
}
public BundleContext getBundleContext() {
return context;
}
/**
* Checks that the given string is contained in the given array.
* @param message the assert point message
* @param array the String array
* @param txt the String to search
*/
public static void assertContains(String message, String[] array, String txt) {
for (int i = 0; i < array.length; i++) {
if (array[i].equals(txt)) {
return;
}
}
fail(formatContainsMessage(message, array, txt));
}
/**
* Checks that the given integer is contained in the given array.
* @param message the assert point message
* @param array the byte array
* @param num the number to search
*/
public static void assertContains(String message, byte[] array, int num) {
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
return;
}
}
Byte[] bytes = new Byte[array.length];
for (int i = 0; i < array.length; i++) {
bytes[i] = new Byte(array[i]);
}
fail(formatContainsMessage(message, bytes, new Integer(num)));
}
/**
* Checks that the given integer is contained in the given array.
* @param message the assert point message
* @param array the short array
* @param num the number to search
*/
public static void assertContains(String message, short[] array, int num) {
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
return;
}
}
Short[] bytes = new Short[array.length];
for (int i = 0; i < array.length; i++) {
bytes[i] = new Short(array[i]);
}
fail(formatContainsMessage(message, bytes, new Integer(num)));
}
/**
* Checks that the given integer is contained in the given array.
* @param message the assert point message
* @param array the integer array
* @param num the number to search
*/
public static void assertContains(String message, int[] array, int num) {
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
return;
}
}
Integer[] bytes = new Integer[array.length];
for (int i = 0; i < array.length; i++) {
bytes[i] = new Integer(array[i]);
}
fail(formatContainsMessage(message, bytes, new Integer(num)));
}
/**
* Checks that the given long is contained in the given array.
* @param message the assert point message
* @param array the long array
* @param num the number to search
*/
public static void assertContains(String message, long[] array, long num) {
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
return;
}
}
Long[] bytes = new Long[array.length];
for (int i = 0; i < array.length; i++) {
bytes[i] = new Long(array[i]);
}
fail(formatContainsMessage(message, bytes, new Long(num)));
}
/**
* Checks that the given float is contained in the given array.
* @param message the assert point message
* @param array the float array
* @param num the number to search
*/
public static void assertContains(String message, float[] array, float num) {
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
return;
}
}
Float[] bytes = new Float[array.length];
for (int i = 0; i < array.length; i++) {
bytes[i] = new Float(array[i]);
}
fail(formatContainsMessage(message, bytes, new Float(num)));
}
/**
* Checks that the given double is contained in the given array.
* @param message the assert point message
* @param array the double array
* @param num the number to search
*/
public static void assertContains(String message, double[] array, double num) {
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
return;
}
}
Double[] bytes = new Double[array.length];
for (int i = 0; i < array.length; i++) {
bytes[i] = new Double(array[i]);
}
fail(formatContainsMessage(message, bytes, new Double(num)));
}
/**
* Checks that the given character is contained in the given array.
* @param message the assert point message
* @param array the character array
* @param character the character to search
*/
public static void assertContains(String message, char[] array, char character) {
for (int i = 0; i < array.length; i++) {
if (array[i] == character) {
return;
}
}
Character[] bytes = new Character[array.length];
for (int i = 0; i < array.length; i++) {
bytes[i] = new Character(array[i]);
}
fail(formatContainsMessage(message, bytes, new Character(character)));
}
/**
* Asserts that two doubles are equal. If they are not an
* AssertionFailedError is thrown with the given message.
* @param message the assert point message
* @param expected the expected double
* @param actual the received double
*/
public static void assertEquals(String message, double expected,
double actual) {
if (expected != actual) {
fail(formatEqualsMessage(message, new Double(expected), new Double(
actual)));
}
}
/**
* Asserts that two objects are not equal. If they are an
* AssertionFailedError is thrown with the given message.
* @param message the assert point message
* @param o1 the unexpected object
* @param o2 the received object
*/
public static void assertNotEquals(String message, Object o1, Object o2) {
if (o1.equals(o2)) {
fail(formatNotEqualsMessage(message, o1, o2));
}
}
/**
* Checks that the given string is contained in the given array.
* @param string the String to search
* @param array the String array
* @return <code>true</code> if the array contains the string
*/
public static boolean contains(String string, String[] array) {
for (int i = 0; array != null && i < array.length; i++) {
if (array[i] != null && array[i].equals(string)) {
return true;
}
}
return false;
}
/**
* Checks that the given integer is contained in the given array.
* @param value the number to search
* @param array the integer array
* @return <code>true</code> if the array contains the value
*/
public static boolean contains(int value, int[] array) {
for (int i = 0; array != null && i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
/**
* Formats a failure message for 'equality' tests.
* @param message the assertion point message
* @param expected the expected value
* @param actual the received value
* @return the computed message
*/
private static String formatEqualsMessage(String message, Object expected,
Object actual) {
String formatted = "";
if (message != null) {
formatted = message + " ";
}
return formatted + "expected:<" + expected + "> but was:<" + actual
+ ">";
}
/**
* Formats a failure message for 'un-equality' tests.
* @param message the assertion point message
* @param o1 the unexpected value
* @param o2 the received value
* @return the computed message
*/
private static String formatNotEqualsMessage(String message, Object o1,
Object o2) {
String formatted = "";
if (message != null) {
formatted = message + " ";
}
return formatted + "o1:<" + o1 + "> is equals to o2:<" + o2 + ">";
}
/**
* Formats a failure message for 'contains' tests.
* @param message the assertion point message
* @param array the array
* @param txt the looked value
* @return the computed message
*/
private static String formatContainsMessage(String message, Object[] array,
Object txt) {
String formatted = "";
if (message != null) {
formatted = message + " ";
}
String arr = null;
for (int i = 0; i < array.length; i++) {
if (arr == null) {
arr = "[" + array[i];
} else {
arr += "," + array[i];
}
}
arr += "]";
return formatted + "array:" + arr + " does not contains:<" + txt + ">";
}
/**
* Returns the service object of a service provided by the specified bundle,
* offering the specified interface and matching the given filter.
*
* @param bundle the bundle from which the service is searched.
* @param itf the interface provided by the searched service.
* @param filter an additional filter (can be {@code null}).
* @return the service object provided by the specified bundle, offering the
* specified interface and matching the given filter.
*/
public static Object getServiceObject(Bundle bundle, String itf,
String filter) {
ServiceReference ref = getServiceReference(bundle, itf, filter);
if (ref != null) {
return bundle.getBundleContext().getService(ref);
} else {
return null;
}
}
/**
* Returns the service objects of the services provided by the specified
* bundle, offering the specified interface and matching the given filter.
*
* @param bundle the bundle from which services are searched.
* @param itf the interface provided by the searched services.
* @param filter an additional filter (can be {@code null}).
* @return the service objects provided by the specified bundle, offering
* the specified interface and matching the given filter.
*/
public static Object[] getServiceObjects(Bundle bundle, String itf,
String filter) {
ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
if (refs != null) {
Object[] list = new Object[refs.length];
for (int i = 0; i < refs.length; i++) {
list[i] = bundle.getBundleContext().getService(refs[i]);
}
return list;
} else {
return new Object[0];
}
}
/**
* Returns the service reference of a service provided by the specified
* bundle, offering the specified interface and matching the given filter.
*
* @param bundle the bundle from which the service is searched.
* @param itf the interface provided by the searched service.
* @param filter an additional filter (can be {@code null}).
* @return a service reference provided by the specified bundle, offering
* the specified interface and matching the given filter. If no
* service is found, {@code null} is returned.
*/
public static ServiceReference getServiceReference(Bundle bundle,
String itf, String filter) {
ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
if (refs.length != 0) {
return refs[0];
} else {
// No service found
return null;
}
}
/**
* Checks if the service is available.
* @param itf the service interface
* @return <code>true</code> if the service is available, <code>false</code>
* otherwise.
*/
public boolean isServiceAvailable(String itf) {
ServiceReference ref = getServiceReference(itf, null);
return ref != null;
}
/**
* Checks if the service is available.
* @param itf the service interface
* @param pid the service pid
* @return <code>true</code> if the service is available, <code>false</code>
* otherwise.
*/
public boolean isServiceAvailableByPID(String itf, String pid) {
ServiceReference ref = getServiceReferenceByPID(itf, pid);
return ref != null;
}
/**
* Returns the service reference of the service provided by the specified
* bundle, offering the specified interface and having the given persistent
* ID.
*
* @param bundle the bundle from which the service is searched.
* @param itf the interface provided by the searched service.
* @param pid the persistent ID of the searched service.
* @return a service provided by the specified bundle, offering the
* specified interface and having the given persistent ID.
*/
public static ServiceReference getServiceReferenceByPID(Bundle bundle,
String itf, String pid) {
String filter = "(" + "service.pid" + "=" + pid + ")";
ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
if (refs == null) {
return null;
} else if (refs.length == 1) {
return refs[0];
} else {
throw new IllegalStateException(
"A service lookup by PID returned several providers ("
+ refs.length + ")" + " for " + itf + " with pid="
+ pid);
}
}
/**
* Returns the service reference of all the services provided in the
* specified bundle, offering the specified interface and matching the given
* filter.
*
* @param bundle the bundle from which services are searched.
* @param itf the interface provided by the searched services.
* @param filter an additional filter (can be {@code null}).
* @return all the service references provided in the specified bundle,
* offering the specified interface and matching the given filter.
* If no service matches, an empty array is returned.
*/
public static ServiceReference[] getServiceReferences(Bundle bundle,
String itf, String filter) {
ServiceReference[] refs = null;
try {
// Get all the service references
refs = bundle.getBundleContext().getServiceReferences(itf, filter);
} catch (InvalidSyntaxException e) {
throw new IllegalArgumentException(
"Cannot get service references: " + e.getMessage());
}
if (refs == null) {
return new ServiceReference[0];
} else {
return refs;
}
}
/**
* Returns the service object of a service provided by the local bundle,
* offering the specified interface and matching the given filter.
*
* @param itf the interface provided by the searched service.
* @param filter an additional filter (can be {@code null}).
* @return the service object provided by the local bundle, offering the
* specified interface and matching the given filter.
*/
public Object getServiceObject(String itf, String filter) {
ServiceReference ref = getServiceReference(itf, filter);
if (ref != null) {
m_references.add(ref);
return context.getService(ref);
} else {
return null;
}
}
/**
* Returns the service object associated with this service reference.
*
* @param ref service reference
* @return the service object.
*/
public Object getServiceObject(ServiceReference ref) {
if (ref != null) {
m_references.add(ref);
return context.getService(ref);
} else {
return null;
}
}
/**
* Returns the service objects of the services provided by the local bundle,
* offering the specified interface and matching the given filter.
*
* @param itf the interface provided by the searched services.
* @param filter an additional filter (can be {@code null}).
* @return the service objects provided by the local bundle, offering the
* specified interface and matching the given filter.
*/
public Object[] getServiceObjects(String itf, String filter) {
ServiceReference[] refs = getServiceReferences(itf, filter);
if (refs != null) {
Object[] list = new Object[refs.length];
for (int i = 0; i < refs.length; i++) {
m_references.add(refs[i]);
list[i] = context.getService(refs[i]);
}
return list;
} else {
return new Object[0];
}
}
/**
* Returns the service reference of a service provided by the local bundle,
* offering the specified interface and matching the given filter.
*
* @param itf the interface provided by the searched service.
* @param filter an additional filter (can be {@code null}).
* @return a service reference provided by the local bundle, offering the
* specified interface and matching the given filter. If no service
* is found, {@code null} is returned.
*/
public ServiceReference getServiceReference(String itf, String filter) {
return getServiceReference(context.getBundle(), itf, filter);
}
/**
* Returns the service reference of a service provided offering the
* specified interface.
*
* @param itf the interface provided by the searched service.
* @return a service reference provided by the local bundle, offering the
* specified interface and matching the given filter. If no service
* is found, {@code null} is returned.
*/
public ServiceReference getServiceReference(String itf) {
return getServiceReference(context.getBundle(), itf, null);
}
/**
* Returns the service reference of the service provided by the local
* bundle, offering the specified interface and having the given persistent
* ID.
*
* @param itf the interface provided by the searched service.
* @param pid the persistent ID of the searched service.
* @return a service provided by the local bundle, offering the specified
* interface and having the given persistent ID.
*/
public ServiceReference getServiceReferenceByPID(String itf, String pid) {
return getServiceReferenceByPID(context.getBundle(), itf, pid);
}
/**
* Returns the service reference of all the services provided in the local
* bundle, offering the specified interface and matching the given filter.
*
* @param itf the interface provided by the searched services.
* @param filter an additional filter (can be {@code null}).
* @return all the service references provided in the local bundle, offering
* the specified interface and matching the given filter. If no
* service matches, an empty array is returned.
*/
public ServiceReference[] getServiceReferences(String itf, String filter) {
return getServiceReferences(context.getBundle(), itf, filter);
}
/**
* Gets the package admin exposed by the framework.
* Fails if the package admin is not available.
* @return the package admin service.
*/
public PackageAdmin getPackageAdmin() {
PackageAdmin pa = (PackageAdmin) getServiceObject(PackageAdmin.class.getName(), null);
if (pa == null) {
fail("No package admin available");
}
return pa;
}
/**
* Refresh the packages.
* Fails if the package admin service is not available.
*/
public void refresh() {
getPackageAdmin().refreshPackages(null);
}
/**
* Waits for a service. Fails on timeout.
* If timeout is set to 0, it sets the timeout to 10s.
* @param itf the service interface
* @param filter the filter
* @param timeout the timeout
*/
public void waitForService(String itf, String filter, long timeout) {
if (timeout == 0) {
timeout = 10000; // Default 10 secondes.
}
ServiceReference[] refs = getServiceReferences(itf, filter);
long begin = System.currentTimeMillis();
if (refs.length != 0) {
return;
} else {
while(refs.length == 0) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// Interrupted
}
long now = System.currentTimeMillis();
if ((now - begin) > timeout) {
fail("Timeout ... no services matching with the request after " + timeout + "ms");
}
refs = getServiceReferences(itf, filter);
}
}
}
/**
* Installs a bundle.
* Fails if the bundle cannot be installed.
* Be aware that you have to uninstall the bundle yourself.
* @param url bundle url
* @return the installed bundle
*/
public Bundle installBundle(String url) {
try {
return context.installBundle(url);
} catch (BundleException e) {
fail("Cannot install the bundle " + url + " : " + e.getMessage());
}
return null; // Can not happen
}
/**
* Installs a bundle.
* Fails if the bundle cannot be installed.
* Be aware that you have to uninstall the bundle yourself.
* @param url bundle url
* @param stream input stream containing the bundle
* @return the installed bundle
*/
public Bundle installBundle(String url, InputStream stream) {
try {
return context.installBundle(url, stream);
} catch (BundleException e) {
fail("Cannot install the bundle " + url + " : " + e.getMessage());
}
return null; // Can not happen
}
/**
* Installs and starts a bundle.
* Fails if the bundle cannot be installed or an error occurs
* during startup. Be aware that you have to uninstall the bundle
* yourself.
* @param url the bundle url
* @return the Bundle object.
*/
public Bundle installAndStart(String url) {
Bundle bundle = installBundle(url);
try {
bundle.start();
} catch (BundleException e) {
fail("Cannot start the bundle " + url + " : " + e.getMessage());
}
return bundle;
}
/**
* Installs and starts a bundle.
* Fails if the bundle cannot be installed or an error occurs
* during startup. Be aware that you have to uninstall the bundle
* yourself.
* @param url the bundle url
* @param stream input stream containing the bundle
* @return the Bundle object.
*/
public Bundle installAndStart(String url, InputStream stream) {
Bundle bundle = installBundle(url, stream);
try {
bundle.start();
} catch (BundleException e) {
fail("Cannot start the bundle " + url + " : " + e.getMessage());
}
return bundle;
}
/**
* Get the bundle by its id.
* @param bundleId the bundle id.
* @return the bundle with the given id.
*/
public Bundle getBundle(long bundleId) {
return context.getBundle(bundleId);
}
/**
* Gets a bundle by its symbolic name.
* Fails if no bundle matches.
* @param name the symbolic name of the bundle
* @return the bundle object.
*/
public Bundle getBundle(String name) {
Bundle[] bundles = context.getBundles();
for (int i = 0; i < bundles.length; i++) {
if (name.equals(bundles[i].getSymbolicName())) {
return bundles[i];
}
}
fail("No bundles with the given symbolic name " + name);
return null; // should not happen
}
}