Wednesday, 20 March 2013

OSGi Assertions and Utilities library 1.2.0 released

A new version 1.2.0 of OSGi Assertions and Utilities library for integration tests is released. 

Changes:
  • EventAdmin-specific utilities and assertions
  • @Test
    public void test_Post_Event() {
        postEvent(getBundleContext(), KNOWHOWLAB_TOPICS_TEST, 200);
    
        assertEvent(KNOWHOWLAB_TOPICS_TEST, 500, TimeUnit.MILLISECONDS);
    }
    
    @Test
    public void test_Post_Event_With_Filters() throws InvalidSyntaxException {
        Map props = new HashMap();
        props.put("prop_key", "val123");
    
        postEvent(getBundleContext(), KNOWHOWLAB_TOPICS_TEST, props, 200);
        assertEvent(KNOWHOWLAB_TOPICS_TEST, FilterUtils.eq("prop_key", "val123"), 500, TimeUnit.MILLISECONDS);
    
        postEvent(getBundleContext(), KNOWHOWLAB_TOPICS_TEST, props, 200);
        try {
            assertEvent(KNOWHOWLAB_TOPICS_TEST, FilterUtils.eq("prop_key", "val555"), 500, TimeUnit.MILLISECONDS);
        } catch (AssertionError e) {
        }
    }
    
  • ConfigurationAdmin-specific utilities and assertions
  • @Test
    public void test_Configuration_manipulations() {
        assertConfigurationUnavailable("test.pid", null, null);
    
        Map config = new HashMap();
        config.put("test.key", "test.value");
        supplyConfiguration(getBundleContext(), "test.pid", null, config, 0);
    
        assertConfigurationUpdated("test.pid", null, null, 500, TimeUnit.MILLISECONDS);
    
        assertConfigurationAvailable("test.pid", null, null);
    
        deleteConfiguration(getBundleContext(), "test.pid", null, 0);
    
        assertConfigurationDeleted("test.pid", null, null, 500, TimeUnit.MILLISECONDS);
    
        assertConfigurationUnavailable("test.pid", null, null);
    }
    
  • PaxExam 3.0.x integration tests
  • Bug fixes and improvements

References:

  1. Sources: GitHub
  2. Mailing List: knowhowlab-osgi-testing


Thank you for your attention. Your feedback is welcome as usual.
Best Regards.

Saturday, 16 March 2013

OSGi integration tests with Bndtools and OSGi assertions library

Table of Contents

  1. Introduction
  2. Create an Integration Test project
  3. Installing external artifacts
  4. Add build dependencies
  5. Write integration tests
  6. Execute integration tests

1. Introduction


This tutorial shows you how to create OSGi integration tests with Bndtools and OSGi Assertions library. The tutorial is a continuation of the original Bndtools Tutorial.

2. Create an Integration Test project


Before start with Integration tests project please check that you finished Bndtools Tutorial and projects org.example.api and org.example.impls are created.

1. From the File menu, select New->Bndtools OSGi Project.
2. Name project org.example.it

3. Select "Integration Testing" project template

4. Edit org.example.tests.ExampleTest class to assert BundleContext
package org.example.tests;

import junit.framework.TestCase;

import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;

public class ExampleTest extends TestCase {

    private final BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext();

    public void testExample() throws Exception {
        assertNotNull(context);
    }
}
5. Right-click on org.example.it project. Run As->Bnd OSGi Test Launcher (JUnit)



3. Installing external artifacts


Now we have to install OSGi Assertions library and dependencies into local repository.
1. Select Local Repository from the list and click Add Bundles to Repository

2. Click Add Exernal JARs... and copy-paste links to artifacts:
- org.apache.servicemix.bundles.junit-4.9_2.jar
- org.knowhowlab.osgi.testing.utils-1.1.0.jar
- org.knowhowlab.osgi.testing.assertions-1.1.0.jar




4. Add build dependencies


Open org.example.test Build tab and add dependencies:
- org.example.api
- org.knowhowlab.osgi.testing.utils
- org.knowhowlab.osgi.testing.assertions
- replace junit.osgi with org.apache.servicemix.bundles.junit (to support JUnit 4.x)



5. Write integration tests


Extend ExampleTest with JUnit 4 tests and OSGi Assertions
package org.example.tests;

import java.util.concurrent.TimeUnit;

import org.example.api.Greeting;
import org.junit.Test;
import org.osgi.framework.Bundle;

import static org.knowhowlab.osgi.testing.assertions.ServiceAssert.*;
import static org.knowhowlab.osgi.testing.assertions.BundleAssert.*;
import static org.knowhowlab.osgi.testing.utils.BundleUtils.*;

public class ExampleTest {

 @Test
    public void testGreetingService() throws Exception {
        assertServiceAvailable(Greeting.class);
    }

 @Test
    public void testGreetingProvider() throws Exception {
        assertBundleState(Bundle.ACTIVE, "org.example.impls.provider");
        
        assertServiceAvailable(Greeting.class);
        
        findBundle(getBundleContext(), "org.example.impls.provider").stop();

        assertServiceUnavailable(Greeting.class, 1, TimeUnit.SECONDS);
    }
}

6. Execute integration tests


1. Update Run Requirements


2. Update Source tab and define manually test case class


3. Right-click on org.example.it project. Run As->Bnd OSGi Test Launcher (JUnit)

Monday, 17 December 2012

OSGi Assertions and Utilities library 1.1.0 released

Hello,

I've released a new version 1.1.0 of OSGi Assertions and Utilities library for integration tests. 

Changes:
  • Asynchronously change Bundle state (install, start, stop, update, uninstall) with and without delays
  •     @Test
        public void test_Start_Bundle_Async() {
            // bundle stopped
            assertBundleState(Bundle.RESOLVED | Bundle.INSTALLED,
                              "org.knowhowlab.osgi.testing.it.test.bundle", 
                              1L, TimeUnit.MILLISECONDS);
            // start bundle in 2 sec
            startBundleAsync(getBundleContext(),  
                             "org.knowhowlab.osgi.testing.it.test.bundle", 
                             2, TimeUnit.SECONDS);
            // bundle is still stopped
            assertBundleState(Bundle.RESOLVED | Bundle.INSTALLED,
                              "org.knowhowlab.osgi.testing.it.test.bundle", 
                              1L, TimeUnit.MILLISECONDS);
            // bundle is active after 5 sec
            assertBundleState(Bundle.ACTIVE,
                              "org.knowhowlab.osgi.testing.it.test.bundle", 
                              5, TimeUnit.SECONDS);
        }
    
  • Asynchronously change Service state (register, update, unregister) with and without delays
  •     @Test
        public void test_RegisterService_Async() {
            // service unregistered
            assertServiceUnavailable(TestService.class);
            // register service in 2 sec
            registerServiceAsync(getBundleContext(), TestService.class, 
                                 new TestService(), null, 2, TimeUnit.SECONDS);
            // service still unregistered
            assertServiceUnavailable(TestService.class);
            // service registered
            assertServiceAvailable(TestService.class, 5, TimeUnit.SECONDS);
        }
    
  • Handle BundleEvents
  •     @Test
        public void test_Bundle_Event() {
            // start bundle in 2 sec
            startBundleAsync(getBundleContext(), 
                             "org.knowhowlab.osgi.testing.it.test.bundle", 
                             2, TimeUnit.SECONDS);
            // expect bundle event within 5 sec
            assertBundleEvent(BundleEvent.STARTED,
                              "org.knowhowlab.osgi.testing.it.test.bundle", 
                              5, TimeUnit.SECONDS);
        }
    
  • Handle ServiceEvents
  •     @Test
        public void test_Service_Event() {
            // register service in 2 sec
            registerServiceAsync(getBundleContext(), TestService.class, 
                                 new TestService(), null, 2, TimeUnit.SECONDS);
            // service registered within 5 sec
            assertServiceEvent(ServiceEvent.REGISTERED, TestService.class, 
                               5, TimeUnit.SECONDS);
        }
    
  • Handle FrameworkEvents
  •     @Test
        public void test_Framework_Event() {
            // change start level
            Executors.newSingleThreadScheduledExecutor()
                       .schedule(new Runnable() {
                                 public void run() {
                                      StartLevel startLevel = 
                                      ServiceUtils.getService(getBundleContext(),
                                                              StartLevel.class);
                                      startLevel.setStartLevel(10);
                                                   }
                                                }, 2, TimeUnit.SECONDS);
    
            // start level changed within 5 sec
            assertFrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, 
                                 0, 5, TimeUnit.SECONDS);
        }
    

References:

  1. Sources: GitHub
  2. Mailing List: knowhowlab-osgi-testing


Thank you for your attention. Your feedback is welcome as usual.
Best Regards.

Sunday, 4 November 2012

OSGi Testing: make your integration/functional tests clearer. A sample with PaxExam

Hello,

two years ago I've posted about small library that I used for my OSGi integration tests. During the last tree weeks I made some changes in it:
  • Sources were moved to GitHub
  • Maven groupId and artifactId were changed
  • Initialization process of OSGi assertions was simplified and does not require BundleContext
  • New utility and assertion methods for Bundles were added.

What is the difference?

You can compare two test methods that test the same functionality.
    /**
     * Test bundle and service without OSGi assertions/utils
     *
     * @throws org.osgi.framework.BundleException
     *                              bundle start/stop problems
     * @throws org.osgi.framework.InvalidSyntaxException
     *                              filter creation problems
     * @throws InterruptedException wait exception
     */
    @Test
    public void test_Without_OSGiAssertions() throws BundleException, InterruptedException, InvalidSyntaxException {
        ServiceTracker packageAdminTracker = new ServiceTracker(getBundleContext(), PackageAdmin.class.getName(), null);
        packageAdminTracker.open();
        PackageAdmin packageAdmin = (PackageAdmin) packageAdminTracker.getService();
        assertNotNull(packageAdmin);
        packageAdminTracker.close();
        Bundle[] bundles = packageAdmin.getBundles("org.knowhowlab.osgi.testing.it.test.bundle", null);
        // asserts that test bundle is installed
        assertNotNull(bundles);
        // gets bundle instance
        Bundle bundle = bundles[0];
        // asserts that test bundle is resolved
        assertTrue(bundle.getState() == Bundle.INSTALLED || bundle.getState() == Bundle.RESOLVED);
        ServiceTracker serviceTracker1 = new ServiceTracker(getBundleContext(), "org.knowhowlab.osgi.testing.it.testbundle.service.Echo", null);
        serviceTracker1.open();
        assertEquals(0, serviceTracker1.size());
        // start bundle
        bundle.start();
        // asserts that test bundle is active
        assertEquals(Bundle.ACTIVE, bundle.getState());
        // asserts that test service is available within 2 seconds
        assertNotNull(serviceTracker1.waitForService(2000));
        // asserts that test service with custom properties is available
        ServiceTracker serviceTracker2 = new ServiceTracker(getBundleContext(), FrameworkUtil.createFilter(
                "(&(" + Constants.OBJECTCLASS + "=org.knowhowlab.osgi.testing.it.testbundle.service.Echo)" +
                        "(testkey=testvalue))"), null);
        serviceTracker2.open();
        assertTrue(serviceTracker2.size() > 0);
        // gets service by class and filter
        Echo echo = (Echo) serviceTracker2.getService();
        // asserts service method call
        assertEquals("test", echo.echo("test"));
        // stops bundle
        bundle.stop();
        // asserts that test bundle is resolved
        assertEquals(Bundle.RESOLVED, bundle.getState());
        // asserts that test service is unregistered
        assertEquals(0, serviceTracker1.size());
    }

    /**
     * The same Test bundle and service with OSGi assertions/utils
     *
     * @throws org.osgi.framework.BundleException
     *          bundle start/stop problems
     * @throws org.osgi.framework.InvalidSyntaxException
     *          filter creation problems
     */
    @Test
    public void test_With_OSGiAssertions() throws BundleException, InvalidSyntaxException {
        // asserts that test bundle is installed
        assertBundleAvailable("org.knowhowlab.osgi.testing.it.test.bundle");
        // asserts that test bundle is resolved
        assertBundleState(Bundle.INSTALLED | Bundle.RESOLVED, "org.knowhowlab.osgi.testing.it.test.bundle", 5, TimeUnit.SECONDS);
        // gets bundle instance
        Bundle bundle = findBundle(bc, "org.knowhowlab.osgi.testing.it.test.bundle");
        // asserts that test service is unavailable
        assertServiceUnavailable("org.knowhowlab.osgi.testing.it.testbundle.service.Echo");
        // start bundle
        bundle.start();
        // asserts that test bundle is active
        assertBundleState(Bundle.ACTIVE, "org.knowhowlab.osgi.testing.it.test.bundle");
        // asserts that test service is available within 2 seconds
        assertServiceAvailable("org.knowhowlab.osgi.testing.it.testbundle.service.Echo", 2, TimeUnit.SECONDS);
        // asserts that test service with custom properties is available
        assertServiceAvailable(and(create(Echo.class), eq("testkey", "testvalue")));
        // gets service by class and filter
        Echo echo = ServiceUtils.getService(getBundleContext(), Echo.class, eq("testkey", "testvalue"));
        // asserts service method call
        assertEquals("test", echo.echo("test"));
        // stops bundle
        bundle.stop();
        // asserts that test bundle is resolved
        assertBundleState(Bundle.RESOLVED, "org.knowhowlab.osgi.testing.it.test.bundle");
        // asserts that test service is unregistered
        assertServiceUnavailable(Echo.class);
    }

How to use the library with PaxExam

Add Maven dependencies to your integration tests pom.xml
        <dependency>
            <groupId>org.knowhowlab.osgi</groupId>
            <artifactId>org.knowhowlab.osgi.testing.utils</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.knowhowlab.osgi</groupId>
            <artifactId>org.knowhowlab.osgi.testing.assertions</artifactId>
            <version>1.0.0</version>
        </dependency>

Include library bundles into PaxExam tests
@Configuration
protected static Option[] baseConfiguration() {
   return options(
...
mavenBundle().groupId("org.knowhowlab.osgi").artifactId("org.knowhowlab.osgi.testing.utils").version(System.getProperty("project.version")),

mavenBundle().groupId("org.knowhowlab.osgi").artifactId("org.knowhowlab.osgi.testing.assertions").version(System.getProperty("project.version")),
...
    );
}

Use in your PaxExam integration tests:
// assert bundle with symbolic name "org.knowhowlab.osgi.testing.utils" is installed into OSGi framework
assertBundleState(Bundle.ACTIVE, "org.knowhowlab.osgi.testing.utils", 5, TimeUnit.SECONDS);
// assert bundle with symbolic name "org.knowhowlab.osgi.testing.utils" is installed into OSGi framework
assertBundleAvailable("org.knowhowlab.osgi.testing.utils");
// assert bundle with symbolic name "org.knowhowlab.osgi.testing.utils" and version "1.0.1"
// is installed into OSGi framework
assertBundleAvailable("org.knowhowlab.osgi.testing.utils", new Version("1.0.1"));
// assert bundle with symbolic name "org.knowhowlab.osgi.testing.utils" and version "2.0.0"
// is not installed into OSGi framework
assertBundleUnavailable("org.knowhowlab.osgi.testing.utils", new Version("2.0.0"));

// assert PackageAdmin service is available in OSGi registry
assertServiceAvailable(PackageAdmin.class, 5, TimeUnit.SECONDS);
// assert MonitorAdmin service is unavailable in OSGi registry
assertServiceUnavailable("org.osgi.service.monitor.MonitorAdmin");
// assert StartLevel service is available in OSGi registry
assertServiceAvailable(StartLevel.class);
// assert PackageAdmin service is available in OSGi registry
assertServiceAvailable(FilterUtils.create(PackageAdmin.class));
// assert MonitorAdmin service is unavailable in OSGi registry
assertServiceUnavailable(FilterUtils.create("org.osgi.service.monitor.MonitorAdmin"));

Here you can find the last sources of the sample.

Thank you for your attention. Your feedback is welcome as usual.
Best Regards.

Friday, 20 May 2011

OSGi universal shell implementation 1.1.0 released

There is a new 1.1.0 version of OSGi universal shell adapters available.

Changes:
  * Added support of defining commands services with Declarative Services

Command service registration with DS:
<?xml version="1.0" encoding="UTF-8"?>
<component name="shell_test.component">
    <implementation class="...ShellTestService"/>

    <service>
        <provide interface="...ShellTestService"/>
    </service>

    <property name="org.knowhowlab.osgi.shell.group.id" type="String" value="test_group_id"/>
    <property name="org.knowhowlab.osgi.shell.group.name" type="String" value="Test commands"/>
    <property name="org.knowhowlab.osgi.shell.commands" type="String">
        bndinfo#bndinfo <bundleId> - Print information for bundle with <bundleId>
        bndsinfo#bndsinfo - Print information for all bundles
    </property>
...
</component>

Maven artifacts:
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>equinox</artifactId>
    <version>1.1.0</version>
</dependency>
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>felix</artifactId>
    <version>1.1.0</version>
</dependency>
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>felix-gogo</artifactId>
    <version>1.1.0</version>
</dependency>
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>knopflerfish</artifactId>
    <version>1.1.0</version>
</dependency>

Cheers,
Dmytro

Saturday, 2 April 2011

OSGi universal shell implementation 1.0.1 released

Hi, There is a new 1.0.1 version of OSGi universal shell adapters available.

Changes:
  * Changed package to org.knowhowlab.osgi.shell
  * Changed maven groupId to org.knowhowlab.osgi.shell
  * Added Apache Felix GoGo Universal Shell Adapter

Maven artifacts:
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>equinox</artifactId>
    <version>1.0.1</version>
</dependency>
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>felix</artifactId>
    <version>1.0.1</version>
</dependency>
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>felix-gogo</artifactId>
    <version>1.0.1</version>
</dependency>
<dependency>
    <groupId>org.knowhowlab.osgi.shell</groupId>
    <artifactId>knopflerfish</artifactId>
    <version>1.0.1</version>
</dependency>

Cheers,
Dmytro

Saturday, 30 October 2010

OSGi Tutorial: 4 ways to activate code in OSGi bundle

Hello everybody!

I would like to present a tutorial in which I show 4 ways how to activate/start code inside your OSGi bundle. All those ways are part of OSGi 4.2 specifications. The goal of the tutorial is to explain in a short form some OSGi specifications chapters with samples. I do not like to make any deep comparison of activation ways, just overview with workable examples. All sources you can find here.

Update 21.10.2013: examples were updated (Fixed an issue with missed Equinox Maven artifacts)

Contents:
  1. Requirements
  2. Use Case details
  3. Bundle Activator
  4. Declarative Services
  5. Blueprint Services
  6. Web Application Bundle
  7. How to run examples
  8. References