Major OSGi feature update
thomas.diesler Sep 7, 2010 11:40 AMThis thread covers a major update in OSGi testing functionality.
ARQ-193 Create auxillary OSGi test bundle
ARQ-235 OSGi Framework does not get stopped
ARQ-190 Remote OSGi bundle testing
ARQ-272 Allow @Deployment to be optional
ARQ-198 Install bundle from maven dependencies
ARQ-194 Support multiple bundle deployments
As always, the accumulated code is at http://github.com/jbosgi/arquillian/tree/jbosgi
ARQ-193 Create auxillary OSGi test bundle
In your ARQ test you can now do
@RunWith(Arquillian.class) public class ARQ193GeneratedTestCase { @Deployment public static Archive<?> createDeployment() { return ShrinkWrap.create(JavaArchive.class, "empty-bundle"); } @Inject public Bundle bundle; ... }
ARQ generates the OSGi manifest for you and also puts the test class in the test archive. If there already is a manifest in the test archive, ARQ appends the necessary infrastructure OSGi headers. The Import-Package header is determined by scanning field, methods, annotations. ARQ cannot however "guess" test specific OSGi headers like a potential Bundle-Activator, etc
For this to work I added the ARQ lifecycle Context to the DeploymentPackager
public interface DeploymentPackager { /** * @param context The test lifecycle context * @param testDeployment Value object containing the application {@link Archive} and other auxiliary library {@link Archive}s. * @return The prepared archive for deployment. */ Archive<?> generateDeployment(Context context, TestDeployment testDeployment); }
ARQ-235 OSGi Framework does not get stopped
Instead of relying on the DeployableContainer start/stop methods, we now boostrap/shutdown the OSGi Framework as part of the deploy/undeploy methods. This gives us @BeforeClass, @AfterClass behaviour (i.e. a fresh OSGi Framework for every test case in the osgi-embedded scenario)
This resolution is considered a hack and should be removed as soon as we have configurable container lifecycle.
ARQ-190 Remote OSGi bundle testing
This feature is critical for the upcoming AS7/OSGi integration. The OSGi RemoteDeployableContainer does not bootstrap a local OSGi Framework instead it connects to a remote MBeanServer using a JSR-160 JMXConnector. The corresponding JMXConnectorServer is started by the jboss-osgi-jmx bundle, which must be deployed on the remote OSGi Framework.
ARQ-272 Allow @Deployment to be optional
You can now do
@RunWith(Arquillian.class) public class ARQ272TestCase { @Inject public Bundle bundle; @Test public void testBundleInjection() throws Exception { assertNotNull("Bundle injected", bundle); assertEquals("Bundle RESOLVED", Bundle.RESOLVED, bundle.getState()); assertEquals(ARQ272TestCase.class.getSimpleName(), bundle.getSymbolicName()); bundle.loadClass(ARQ272TestCase.class.getName()); bundle.stop(); assertEquals("Bundle RESOLVED", Bundle.RESOLVED, bundle.getState()); bundle.uninstall(); assertEquals("Bundle UNINSTALLED", Bundle.UNINSTALLED, bundle.getState()); } }
Because ARQ always adds the test class to the @Deployment archive, there is little reason why an OSGi test must supply an empty archive. I modified DeploymentAnnotationArchiveGenerator such that it generates an empty archive if there is no @Deployment annotation in the test case.
ARQ-198 Install bundle from maven dependencies
OSGi test cases support injection of an OSGiContainer. On that container there are a number of methods that let you install bundles from the classpath and the local maven repository like this
@Test public void testInstallBundleAlreadyInstalled() throws Exception { Bundle arqBundle = container.getBundle(ARQUILLIAN_OSGI_BUNDLE, null); assertNotNull("ARQ bundle installed", arqBundle); Bundle result = container.installBundle(ARQUILLIAN_OSGI_BUNDLE); assertEquals(arqBundle, result); result = container.installBundle("org.jboss.arquillian.protocol", ARQUILLIAN_OSGI_BUNDLE, getArquilianVersion()); assertEquals(arqBundle, result); }
ARQ-194 Support multiple bundle deployments
OSGi test methods can now callback to the client and have a test bundle generated on demand. This is also done via the injected OSGiContainer.
@RunWith(Arquillian.class) public class ARQ194TestCase { @Inject public OSGiContainer container; @Test public void testGeneratedBundle() throws Exception { Archive<?> archive = container.getTestArchive("arq194-bundle"); Bundle bundle = container.installBundle(archive); ... } public static class BundleArchiveProvider implements ArchiveProvider { public JavaArchive getTestArchive(String name) { final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, name); archive.addClasses(ARQ194Activator.class, ARQ194Service.class); return archive; } } }
The test case contains an inner class that implements ArchiveProvider. During test method execution the OSGiContainer calls back to the client to invoke ArchiveProvider.getTestArchive(String). The assets that are packaged by in the JavaArchive are taken from the test client's classpath and not from test bundle's OSGi class space.
The injected OSGiContainer works for embedded and remote OSGi Frameworks. In case of the remote scenario, ARQ sets up two-way communication via the JMX protocol
--------------------------------------
We are currently working on migrating all of our remaining Husky tests to Arquillian, which is a prerequisite for the upcoming 1.0.0.Beta9 release. I would reassign the above ARQ issues when we are done.
cheers
-thomas