FELIX-1030: add device access tests
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@765537 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/ActivatorTest.java b/deviceaccess/src/test/java/org/apache/felix/das/ActivatorTest.java
new file mode 100644
index 0000000..bb1656f
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/ActivatorTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.das;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.apache.felix.dependencymanager.Service;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.BundleContext;
+
+
+
+/**
+ *
+ * Tests the Activator.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ActivatorTest {
+
+
+
+ private Activator m_activator;
+
+ @Mock
+ private BundleContext m_context;
+
+ @Mock
+ private DependencyManager m_manager;
+
+ @Before
+ public void before() {
+
+ MockitoAnnotations.initMocks(this);
+ m_activator = new Activator();
+
+ }
+
+
+
+
+ @Test
+ public void VerifyActivatorInit() throws Exception {
+
+ m_activator.init(m_context, m_manager);
+
+ Mockito.verify(m_manager).add(Mockito.isA(Service.class));
+
+ }
+
+ /**
+ * Verify we do not actively perform any actions during the destroy.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void VerifyActivatorDestroy() throws Exception {
+
+ m_activator.destroy(m_context, m_manager);
+
+ Mockito.verifyZeroInteractions(m_context);
+ Mockito.verifyZeroInteractions(m_manager);
+
+ }
+
+
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/DeviceManagerTest.java b/deviceaccess/src/test/java/org/apache/felix/das/DeviceManagerTest.java
new file mode 100644
index 0000000..de384b2
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/DeviceManagerTest.java
@@ -0,0 +1,914 @@
+/*
+ * 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.das;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+
+import org.apache.felix.das.util.DriverLoader;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.device.Constants;
+import org.osgi.service.device.Device;
+import org.osgi.service.device.Driver;
+import org.osgi.service.device.DriverLocator;
+import org.osgi.service.device.DriverSelector;
+import org.osgi.service.device.Match;
+import org.osgi.service.log.LogService;
+
+
+
+/**
+ * Test the actual implementation.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DeviceManagerTest
+{
+
+ @Mock
+ private DeviceManager m_manager;
+
+ @Mock Bundle m_systemBundle;
+
+ @Mock
+ private LogService m_log;
+
+
+ private BundleContext m_context;
+
+
+ private OSGiMock m_osgi;
+
+
+ @Before
+ public void setUp() throws Exception
+ {
+ m_osgi = new OSGiMock();
+
+ MockitoAnnotations.initMocks(this);
+
+ m_context = m_osgi.getBundleContext();
+
+ m_manager = new DeviceManager( m_context );
+
+ Utils.invoke( m_manager, "init" );
+
+ Utils.inject( m_manager, LogService.class, m_log );
+
+ Mockito.when( m_context.getBundle( 0 ) ).thenReturn( m_systemBundle );
+
+ final CountDownLatch latch = new CountDownLatch( 1 );
+
+ Answer<Integer> answer = new Answer<Integer>()
+ {
+ public Integer answer(InvocationOnMock invocation) throws Throwable
+ {
+ latch.countDown();
+ return Bundle.ACTIVE;
+ }
+ };
+
+ Mockito.when( m_systemBundle.getState() ).thenAnswer( answer );
+
+ Utils.invoke( m_manager, "start" );
+ latch.await( 5, TimeUnit.SECONDS );
+
+ Mockito.when( m_context.installBundle(Mockito.isA( String.class ), ( InputStream ) Mockito.isNull() ) )
+ .thenThrow(new NullPointerException( "inputstream is null exception" ) );
+ }
+
+
+ @After
+ public void tearDown() throws Exception
+ {
+ Utils.invoke( m_manager, "stop" );
+ Utils.invoke( m_manager, "destroy" );
+ }
+
+ private Driver tstCreateDriver( String driverId, int match ) throws Exception
+ {
+ Properties p = new Properties();
+ p.put( Constants.DRIVER_ID, driverId );
+ p.put( "match", Integer.toString( match ) );
+
+ return tstCreateDriver( p );
+ }
+
+
+ private Driver tstCreateDriver( Properties p ) throws Exception
+ {
+ Driver driver = Mockito.mock( Driver.class );
+
+ ServiceReference ref = m_osgi.registerService(
+ new String[]{ Driver.class.getName() }, driver, p );
+
+ MatchAnswer answer = new MatchAnswer( ref );
+
+ Mockito.when( driver.match( Mockito.isA( ServiceReference.class ) ) )
+ .thenAnswer( answer );
+
+ Bundle bundle = m_osgi.getBundle( ref );
+ Mockito.when( bundle.getLocation() )
+ .thenReturn(
+ DriverLoader.DRIVER_LOCATION_PREFIX + p.getProperty( Constants.DRIVER_ID ));
+
+ return driver;
+ }
+
+
+ private Device tstCreateDevice( String[] cat )
+ {
+ return tstCreateDevice( cat, true );
+ }
+
+
+ private Device tstCreateDevice( String[] cat, boolean isDevice )
+ {
+ Properties p = new Properties();
+ p.put( Constants.DEVICE_CATEGORY, cat );
+ if ( isDevice )
+ {
+ return ( Device ) tstCreateService( p, Device.class );
+ }
+ return tstCreateService( p, Object.class );
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private <T> T tstCreateService( Properties p, Class<?> iface )
+ {
+ T svc = ( T ) Mockito.mock( iface, iface.getSimpleName() );
+
+ m_osgi.registerService( new String[]
+ { iface.getName() }, svc, p );
+ return svc;
+ }
+
+
+ /**
+ *
+ * prepared all expected behavior for the installation of a dynamic driver
+ * bundle based on an acquired InputStream.
+ *
+ *
+ * @param driverId
+ * @param match
+ * @param in
+ * @return
+ * @throws BundleException
+ * @throws Exception
+ */
+ private Driver tstExpectInstallDriverBundle( String driverId, int match, InputStream in ) throws BundleException,
+ Exception
+ {
+
+ Bundle bundle = Mockito.mock( Bundle.class, "driverBundle" );
+ Mockito.when( m_context.installBundle(
+ Mockito.eq( "_DD_" + driverId ), Mockito.eq( in ) ) )
+ .thenReturn( bundle );
+
+ final Driver driver = tstCreateDriver( driverId, match );
+ final ServiceReference driverRef = m_osgi.getReference( driver );
+
+ Answer<Object> answer = new Answer<Object>()
+ {
+
+ public Object answer(InvocationOnMock invocation) throws Throwable
+ {
+ m_manager.driverAdded( driverRef, driver );
+ return null;
+ }
+ };
+
+ //bundle start leads to the addition of the driver to
+ //the device manager.
+ Mockito.doAnswer(answer).when(bundle).start();
+
+ Mockito.when( bundle.getRegisteredServices() )
+ .thenReturn( new ServiceReference[]{ driverRef } );
+
+ return driver;
+ }
+
+
+ /**
+ * returns a CountDownLatch.
+ * This countdown latch will count down as soon as <code>Device.noDriverFound()</code>
+ * has been called.
+ * @param device the Device
+ * @return the countdown latch
+ */
+ private CountDownLatch tstExpectNoDriverFound( Device device )
+ {
+ final CountDownLatch latch = new CountDownLatch( 1 );
+
+ //countdown when noDriverFound is called
+ Answer<Object> answer = new Answer<Object>()
+ {
+ public Object answer(InvocationOnMock invocation) throws Throwable
+ {
+ latch.countDown();
+ return null;
+ }
+ };
+
+ Mockito.doAnswer( answer ).when(device).noDriverFound();
+
+ return latch;
+
+ }
+
+
+ private CountDownLatch tstExpectAttach( Driver driver, Object device ) throws Exception
+ {
+ final CountDownLatch latch = new CountDownLatch( 1 );
+ Answer<String> answer = new Answer<String>()
+ {
+ public String answer(InvocationOnMock invocation) throws Throwable
+ {
+ latch.countDown();
+ return null;
+ }
+ };
+
+ //successful attach
+ Mockito.when( driver.attach( m_osgi.getReference( device ) ) )
+ .thenAnswer( answer );
+
+ return latch;
+ }
+
+ private CountDownLatch tstExpectUnloadDriverBundle( Driver driver ) throws BundleException {
+
+
+ final CountDownLatch latch = new CountDownLatch( 1 );
+ Answer<String> answer = new Answer<String>()
+ {
+ public String answer(InvocationOnMock invocation) throws Throwable
+ {
+ latch.countDown();
+ return null;
+ }
+ };
+
+ Bundle bundle = m_osgi.getBundle( m_osgi.getReference( driver ) );
+
+ Mockito.doAnswer(answer).when( bundle ).uninstall();
+
+ return latch;
+ }
+
+ /**
+ * This method generates behavior on the provided DriverLocator.
+ *
+ * The given driver Ids and their matches are expected as drivers found
+ * by this driver locator.
+ * Also, if a driver is found, we can also expect that loadDriver is called;
+ * resulting in an InputStream. That particular input stream should, when installed
+ * using a bundle context, lead to the registration of a driver with
+ * the correcsponding driver id.
+ *
+ * @param locator
+ * @param driverIds
+ * @param matches
+ * @return
+ * @throws Exception
+ */
+ private Map<String, Driver> tstExpectDriverLocatorFor( final DriverLocator locator, final String[] driverIds,
+ int[] matches ) throws Exception
+ {
+
+ Mockito.when( locator.findDrivers( Mockito.isA( Dictionary.class ) ) )
+ .thenReturn( driverIds );
+
+ Map<String, Driver> drivers = new HashMap<String, Driver>();
+
+ final Map<String, InputStream> streams = new HashMap<String, InputStream>();
+
+ for ( String driverId : driverIds )
+ {
+ InputStream in = Mockito.mock(InputStream.class, "[InputStream for: " + driverId + "]");
+ streams.put( driverId, in );
+ }
+
+ Answer<InputStream> answer = new Answer<InputStream>()
+ {
+ public InputStream answer(InvocationOnMock invocation) throws Throwable
+ {
+ final String id = invocation.getArguments()[0].toString();
+
+ for ( String driverId : driverIds )
+ {
+ if ( id.equals( driverId ) )
+ {
+ return streams.get( id );
+ }
+ }
+ throw new IOException( "no such driverId defined in this locator: " + locator );
+ }
+ };
+
+
+ Mockito.when( locator.loadDriver( Mockito.isA( String.class ) ) )
+ .thenAnswer( answer );
+
+ int i = 0;
+ for ( String driverId : driverIds )
+ {
+ Driver driver = tstExpectInstallDriverBundle( driverId, matches[i], streams.get( driverId ) );
+ drivers.put( driverId, driver );
+ i++;
+ }
+
+ return drivers;
+
+ }
+
+
+ /**
+ * does not really test anything special, but ensures that the internal
+ * structure is able to parse the addition
+ */
+ @Test
+ public void LocatorAdded()
+ {
+
+ DriverLocator locator = Mockito.mock( DriverLocator.class );
+ m_manager.locatorAdded( locator );
+
+ }
+
+
+ /**
+ * does not really test anything special, but ensures that the internal
+ * structure is able to parse the addition/ removal
+ */
+ @Test
+ public void LocatorRemoved()
+ {
+
+ DriverLocator locator = Mockito.mock( DriverLocator.class );
+
+ m_manager.locatorAdded( locator );
+ m_manager.locatorRemoved( locator );
+
+ }
+
+
+ /**
+ * does not really test anything special, but ensures that the internal
+ * structure is able to parse the addition
+ * @throws Exception
+ */
+ @Test
+ public void DriverAdded() throws Exception
+ {
+
+ Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", 1 );
+
+ m_manager.driverAdded( m_osgi.getReference( driver ), driver );
+
+ }
+
+
+ /**
+ * does not really test anything special, but ensures that the internal
+ * structure is able to parse the addition/ removal
+ * @throws Exception
+ */
+ @Test
+ public void DriverRemoved() throws Exception
+ {
+
+ Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", 1 );
+
+ ServiceReference ref = m_osgi.getReference( driver );
+
+ m_manager.driverAdded( ref, driver );
+ m_manager.driverRemoved( ref );
+ }
+
+ /**
+ * does not really test anything special, but ensures that the internal
+ * structure is able to parse the addition/ removal
+ * @throws Exception
+ */
+ @Test
+ public void DeviceRemoved() throws Exception
+ {
+
+ Properties p = new Properties();
+ p.put(Constants.DEVICE_CATEGORY, new String[]{"dummy"});
+
+ ServiceReference ref = OSGiMock.createReference(p);
+
+ Object device = new Object();
+
+ m_manager.deviceAdded( ref, device );
+ m_manager.deviceRemoved( ref );
+ }
+
+ /**
+ * does not really test anything special, but ensures that the internal
+ * structure is able to parse the addition/ removal
+ * @throws Exception
+ */
+ @Test
+ public void DeviceModified() throws Exception
+ {
+
+ Properties p = new Properties();
+ p.put(Constants.DEVICE_CATEGORY, new String[]{"dummy"});
+
+ ServiceReference ref = OSGiMock.createReference(p);
+ Object device = new Object();
+
+ m_manager.deviceAdded( ref, new Object() );
+ m_manager.deviceModified(ref, device);
+ }
+ //intended flow, various configurations
+ /**
+ * We add a device, but there are no driver locators, so
+ * the noDriverFound method must be called
+ * @throws InterruptedException
+ */
+ @Test
+ public void DeviceAddedNoDriverLocator() throws InterruptedException
+ {
+
+ //create a mocked device
+ Device device = tstCreateDevice( new String[]
+ { "org.apache.felix" } );
+
+ CountDownLatch latch = tstExpectNoDriverFound( device );
+
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+ if ( !latch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected call noDriverFound" );
+ }
+
+ }
+
+
+ /**
+ * We add a device, but there are no driver locators, however, there is a driver
+ * that matches. Thus an attach must follow.
+ * @throws Exception
+ */
+ @Test
+ public void DeviceAddedNoDriverLocatorSuccessfulAttach() throws Exception
+ {
+
+ Device device = tstCreateDevice( new String[] { "org.apache.felix" } );
+ Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", 1 );
+
+ CountDownLatch attachLatch = tstExpectAttach( driver, device );
+
+ m_manager.driverAdded( m_osgi.getReference( driver ), driver );
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+ if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected attach" );
+ }
+
+ }
+
+
+ /**
+ * We add a device, but there are no driver locators, however, there is a driver
+ * but it sadly doesn't match. Thus a <code>noDriverFound()</code> is called.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void DeviceAddedNoDriverLocatorAttachFails() throws Exception
+ {
+
+ Device device = tstCreateDevice( new String[] { "org.apache.felix" } );
+ Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", Device.MATCH_NONE );
+
+ CountDownLatch attachLatch = tstExpectNoDriverFound( device );
+
+ m_manager.driverAdded( m_osgi.getReference( driver ), driver );
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+ if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected attach" );
+ }
+
+ }
+
+
+ /**
+ * We add a device while there's one driverlocator that will successfully
+ * locate and load two driver bundles. We expect a <code>Driver.attach()</code> for
+ * the best matching driver. There's already a driver loaded that should not match.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void DeviceAddedWithADriverLocator() throws Exception
+ {
+
+ final String driverId1 = "org.apache.felix.driver-1.0";
+ final String driverId2 = "org.apache.felix.driver-1.1";
+ final String notMatchingButLoadedDriverId = "dotorg.apache.felix.driver-1.0";
+
+
+ DriverLocator locator = Mockito.mock( DriverLocator.class );
+
+ Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator,
+ new String[] { driverId1, driverId2 },
+ new int[] { 30, 3 } );
+
+ Driver noMatcher = tstCreateDriver( notMatchingButLoadedDriverId, 100 );
+
+ Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
+
+ final CountDownLatch attachLatch = tstExpectAttach( drivers.get( driverId1 ), device );
+
+ final CountDownLatch unloadDriverLatch = tstExpectUnloadDriverBundle( drivers.get ( driverId2 ) );
+
+ m_manager.locatorAdded( locator );
+
+ m_manager.driverAdded( m_osgi.getReference( noMatcher ), noMatcher );
+
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+ if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected an attach" );
+ }
+
+ //since driver1 is attached, we expect an uninstall()
+ //of all other (dynamically loaded) driver bundles
+ if ( !unloadDriverLatch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected an unload" );
+ }
+
+ }
+
+ @Test
+ public void DeviceAddedWithADriverLocatorUnloadFails() throws Exception
+ {
+
+ final String driverId1 = "org.apache.felix.driver-1.0";
+ final String driverId2 = "org.apache.felix.driver-1.1";
+ final String notMatchingButLoadedDriverId = "dotorg.apache.felix.driver-1.0";
+
+
+ DriverLocator locator = Mockito.mock( DriverLocator.class );
+
+ Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator,
+ new String[] { driverId1, driverId2 },
+ new int[] { 30, 3 } );
+
+ Driver noMatcher = tstCreateDriver( notMatchingButLoadedDriverId, 100 );
+
+ Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
+
+ final CountDownLatch attachLatch = tstExpectAttach( drivers.get( driverId1 ), device );
+
+ final CountDownLatch unloadDriverLatch = new CountDownLatch( 1 );
+
+ ServiceReference driver2Ref = m_osgi.getReference( drivers.get( driverId2 ) );
+ Bundle driver2Bundle = m_osgi.getBundle( driver2Ref );
+
+ Answer<Object> answer = new Answer<Object>() {
+
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ try {
+ throw new BundleException("test driverBundle uninstall failed");
+ }
+ finally {
+ unloadDriverLatch.countDown();
+ }
+ }
+ };
+
+ Mockito.doAnswer(answer).when(driver2Bundle).uninstall();
+
+ m_manager.locatorAdded( locator );
+
+ m_manager.driverAdded( m_osgi.getReference( noMatcher ), noMatcher );
+
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+ if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected an attach" );
+ }
+
+ if ( !unloadDriverLatch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected an unload" );
+ }
+
+
+ //since driver1 is attached, we expect an uninstall()
+ //of all other (dynamically loaded) driver bundles
+ //Driver driver = drivers.get( driverId2 );
+ //tstVerifyBundleUninstall( driver );
+ }
+
+ /**
+ * Two drivers equally match the device. There is a driver selector
+ * that comes to the rescue that selects driver2.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void EqualMatchWithDriverSelector() throws Exception
+ {
+
+ final String driverId1 = "org.apache.felix.driver-1.0";
+ final String driverId2 = "org.apache.felix.driver-1.1";
+
+ DriverLocator locator = Mockito.mock( DriverLocator.class );
+
+ Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator,
+ new String[] { driverId1, driverId2 },
+ new int[] { 20, 20 } );
+
+ Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
+
+ DriverSelector selector = Mockito.mock( DriverSelector.class );
+
+ SelectorMatcher matcher = new SelectorMatcher( driverId2 );
+
+ Mockito.when( selector.select(
+ Mockito.eq( m_osgi.getReference( device ) ),
+ Mockito.isA(Match[].class) ) ).thenAnswer( matcher );
+
+ final CountDownLatch attachLatch = tstExpectAttach( drivers.get( driverId2 ), device );
+
+
+ Utils.inject( m_manager, DriverSelector.class, selector );
+
+ m_manager.locatorAdded( locator );
+
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+ if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected an attach" );
+ }
+
+
+ //driver2 is attached, so driver1 bundle should uninstall.
+ //Driver driver = drivers.get( driverId1 );
+ //tstVerifyBundleUninstall( driver );
+
+ }
+
+
+ //exceptional flow
+ @Test
+ public void DriverLocator_findDriverFails() throws Exception
+ {
+
+ final CountDownLatch latch = new CountDownLatch( 1 );
+
+ Answer<String[]> answer = new Answer<String[]>()
+ {
+
+ public String[] answer(InvocationOnMock invocation) throws Throwable
+ {
+ latch.countDown();
+ throw new RuntimeException( "test exception" );
+ }
+ };
+
+ DriverLocator locator = Mockito.mock( DriverLocator.class, "locator" );
+ Mockito.when( locator.findDrivers( Mockito.isA( Dictionary.class ) ) )
+ .thenAnswer( answer );
+
+ Device device = tstCreateDevice( new String[]
+ { "org.apache.felix" } );
+
+ final CountDownLatch latch2 = new CountDownLatch( 1 );
+
+ Answer<Object> answer2 = new Answer<Object>()
+ {
+ public Object answer(InvocationOnMock invocation) throws Throwable
+ {
+ latch2.countDown();
+ return null;
+ }
+ };
+
+ Mockito.doAnswer(answer2).when(device).noDriverFound();
+
+
+ m_manager.locatorAdded( locator );
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+ if ( !latch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected a call to DriverLocator.findDrivers" );
+ }
+
+ if ( !latch2.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected a call to Driver.noDriverFound" );
+ }
+
+ }
+
+
+ /**
+ * This test verified correct behavior when after a driver
+ * attach led to a referral, this referral leads to an exception.
+ *
+ *
+ * @throws Exception
+ */
+ @Ignore
+ public void DriverReferral_ReferralFails() throws Exception
+ {
+
+ final String referredDriver = "org.apache.felix.driver-2.0";
+
+ String[] driverIds = new String[]
+ { "org.apache.felix.driver-1.0", "org.apache.felix.driver-1.1" };
+
+ int[] driverMatches = new int[]{ 1, Device.MATCH_NONE };
+
+ DriverLocator locator = Mockito.mock( DriverLocator.class, "locator for v1.x" );
+ Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator, driverIds, driverMatches );
+
+
+ DriverLocator locatorv2 = Mockito.mock( DriverLocator.class, "locator for v2.x (fails always)" );
+ Mockito.when( locatorv2.findDrivers( Mockito.isA( Dictionary.class ) ) )
+ .thenReturn( null );
+
+ Mockito.when( locatorv2.loadDriver( Mockito.startsWith( "org.apache.felix.driver-1" ) ) )
+ .thenReturn( null );
+
+ InputStream referredInputStream = Mockito.mock(InputStream.class);
+ Mockito.when( locatorv2.loadDriver( referredDriver ) ).thenReturn( referredInputStream );
+
+
+ //this is what initial driver referral eventually leads
+ //to: the loading of a driver bundle
+ //we fake it, so that it fails
+ Mockito.when( m_context.installBundle(
+ Mockito.anyString(),
+ Mockito.isA( InputStream.class ) ) )
+ .thenThrow(new BundleException( "test exception" ) );
+
+ Driver matched = drivers.get( "org.apache.felix.driver-1.0" );
+
+ final CountDownLatch latch = new CountDownLatch( 1 );
+
+ Answer<String> driver10_attach = new Answer<String>()
+ {
+ public String answer(InvocationOnMock invocation) throws Throwable
+ {
+ System.out.println("driver10_attach()");
+ latch.countDown();
+ return referredDriver;
+ }
+ };
+
+ Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
+
+
+ Mockito.when( matched.match( m_osgi.getReference( device ) ) ).thenReturn( 10 );
+
+ Mockito.when( matched.attach( Mockito.isA( ServiceReference.class ) ) )
+ .thenAnswer( driver10_attach );
+
+// for ( String driverId : driverIds )
+// {
+// Driver driver = drivers.get( driverId );
+// tstExpectBundleUninstall( driver );
+// }
+
+
+ //the actual test
+
+ m_manager.locatorAdded( locator );
+ m_manager.locatorAdded( locatorv2 );
+
+ //depman induced callback
+ m_manager.deviceAdded( m_osgi.getReference( device ), device );
+
+
+ if ( !latch.await( 5, TimeUnit.SECONDS ) )
+ {
+ Assert.fail( "expected an attach to: " + driverIds[0] );
+ }
+
+
+ Mockito.verify(device).noDriverFound();
+ }
+
+ /**
+ * @author dennisg
+ *
+ */
+ private class MatchAnswer implements Answer<Integer>
+ {
+
+ private final ServiceReference m_driverRef;
+
+ public MatchAnswer( ServiceReference driverRef )
+ {
+ m_driverRef = driverRef;
+ }
+
+
+ public Integer answer(InvocationOnMock invocation) throws Throwable
+ {
+ ServiceReference deviceRef = ( ServiceReference ) invocation.getArguments()[0];
+ String[] categories = String[].class.cast( deviceRef.getProperty( Constants.DEVICE_CATEGORY ) );
+ String driverId = String.class.cast( m_driverRef.getProperty( Constants.DRIVER_ID ) );
+
+ for ( String string : categories )
+ {
+ if ( driverId.startsWith( string ) )
+ {
+ Object match = m_driverRef.getProperty( "match" );
+ return Integer.valueOf( match.toString() );
+ }
+ }
+ return Device.MATCH_NONE;
+ }
+
+ }
+
+
+ private class SelectorMatcher implements Answer<Integer>
+ {
+
+ private String m_driverId;
+
+
+ public SelectorMatcher( String driverId )
+ {
+ m_driverId = driverId;
+ }
+
+ public Integer answer(InvocationOnMock invocation) throws Throwable
+ {
+ int i = 0;
+ Match[] matches = (Match[])invocation.getArguments()[1];
+
+ for ( Match match : matches )
+ {
+ if ( match.getDriver().getProperty( Constants.DRIVER_ID ).equals( m_driverId ) )
+ {
+ return i;
+ }
+ i++;
+ }
+ return DriverSelector.SELECT_NONE;
+ }
+
+
+ }
+
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/DriverAttributesTest.java b/deviceaccess/src/test/java/org/apache/felix/das/DriverAttributesTest.java
new file mode 100644
index 0000000..56cef12
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/DriverAttributesTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.das;
+
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.device.Device;
+import org.osgi.service.device.Driver;
+
+/**
+ *
+ * Some simple tests for the DriverAttributes class.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ *
+ */
+public class DriverAttributesTest {
+
+
+ private DriverAttributes m_attributes;
+
+ @Mock
+ private ServiceReference m_ref;
+
+ @Mock
+ private Driver m_driver;
+
+ @Mock
+ private Bundle m_bundle;
+
+ @Before
+ public void setUp() throws Exception {
+
+ MockitoAnnotations.initMocks(this);
+
+ Mockito.when(m_ref.getBundle()).thenReturn(m_bundle);
+
+ Mockito.when(m_bundle.getLocation()).thenReturn("_DD_test-driverbundle");
+
+ m_attributes = new DriverAttributes(m_ref, m_driver);
+ }
+
+
+ @Test
+ public void VerifyDriverReferenceReturned() throws Exception {
+
+ Assert.assertEquals(m_ref, m_attributes.getReference());
+ }
+
+ @Test
+ public void VerifyDriverInUseByDevice() throws Exception {
+
+ ServiceReference ref = Mockito.mock(ServiceReference.class);
+
+ Mockito.when(ref.getProperty(Constants.OBJECTCLASS))
+ .thenReturn(new String[]{Object.class.getName()});
+
+ Mockito.when(ref.getProperty(
+ org.osgi.service.device.Constants.DEVICE_CATEGORY))
+ .thenReturn(new String[]{"dummy"});
+
+ Mockito.when(m_bundle.getServicesInUse()).thenReturn(new ServiceReference[]{ref});
+
+ m_attributes.tryUninstall();
+
+ Mockito.verify(m_bundle).getLocation();
+ Mockito.verify(m_bundle).getServicesInUse();
+ Mockito.verifyNoMoreInteractions(m_bundle);
+
+ }
+
+ @Test
+ public void VerifyDriverInUseByDeviceInstance() throws Exception {
+
+ ServiceReference ref = Mockito.mock(ServiceReference.class);
+
+ Mockito.when(ref.getProperty(Constants.OBJECTCLASS)).thenReturn(new String[]{Device.class.getName()});
+ Mockito.when(ref.getProperty(
+ org.osgi.service.device.Constants.DEVICE_CATEGORY))
+ .thenReturn(new String[]{"dummy"});
+
+ Mockito.when(m_bundle.getServicesInUse()).thenReturn(new ServiceReference[]{ref});
+
+ m_attributes.tryUninstall();
+
+ Mockito.verify(m_bundle).getLocation();
+ Mockito.verify(m_bundle).getServicesInUse();
+ Mockito.verifyNoMoreInteractions(m_bundle);
+
+ }
+
+
+ @Test
+ public void VerifyDriverInUseByNoDevice() throws Exception {
+
+ ServiceReference ref = Mockito.mock(ServiceReference.class);
+
+ Mockito.when(ref.getProperty(Constants.OBJECTCLASS)).thenReturn(new String[]{Object.class.getName()});
+ Mockito.when(m_bundle.getServicesInUse()).thenReturn(new ServiceReference[]{ref});
+
+ m_attributes.tryUninstall();
+
+ Mockito.verify(m_bundle).getLocation();
+ Mockito.verify(m_bundle).getServicesInUse();
+ Mockito.verify(m_bundle).uninstall();
+
+ }
+ @Test
+ public void VerifyDriverNotInUseLeadsToUnInstall1() throws Exception {
+
+ Mockito.when(m_bundle.getServicesInUse()).thenReturn(new ServiceReference[0]);
+
+ m_attributes.tryUninstall();
+
+ Mockito.verify(m_bundle).uninstall();
+
+
+ }
+
+ @Test
+ public void VerifyDriverNotInUseLeadsToUnInstall2() throws Exception {
+
+ m_attributes.tryUninstall();
+
+ Mockito.verify(m_bundle).uninstall();
+
+ }
+
+ @Test
+ public void VerifyAttachCalledOnDriver() throws Exception {
+
+
+ ServiceReference ref = Mockito.mock(ServiceReference.class);
+ m_attributes.attach(ref);
+
+ Mockito.verify(m_driver).attach(Mockito.eq(ref));
+
+ }
+
+ @Test
+ public void VerifyMatchCalledOnDriver() throws Exception {
+
+
+ ServiceReference ref = Mockito.mock(ServiceReference.class);
+ m_attributes.match(ref);
+
+ Mockito.verify(m_driver).match(Mockito.eq(ref));
+
+ }
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/OSGiMock.java b/deviceaccess/src/test/java/org/apache/felix/das/OSGiMock.java
new file mode 100644
index 0000000..c0acf3e
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/OSGiMock.java
@@ -0,0 +1,166 @@
+/*
+ * 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.das;
+
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+
+/**
+ *
+ * a very simple mock of an osgi framework. enables the registration of services.
+ * automatically generates mocked service references for them.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class OSGiMock
+{
+
+ @Mock
+ private BundleContext m_context;
+
+ private Map<Object, ServiceReference> m_references;
+
+ private Map<ServiceReference, Bundle> m_bundles;
+
+ private int m_serviceIndex = 1;
+
+ public OSGiMock()
+ {
+ MockitoAnnotations.initMocks(this);
+ m_references = new HashMap<Object, ServiceReference>();
+ m_bundles = new HashMap<ServiceReference, Bundle>();
+ }
+
+ public static ServiceReference createReference(final Properties p)
+ {
+ ServiceReference ref = Mockito.mock( ServiceReference.class );
+
+ Mockito.when(ref.getProperty(Mockito.anyString())).thenAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return p.get(invocation.getArguments()[0].toString());
+ }
+ });
+
+ Mockito.when(ref.getPropertyKeys()).thenAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return p.keySet().toArray(new String[0]);
+ }
+ });
+
+
+ return ref;
+ }
+
+
+
+ public BundleContext getBundleContext()
+ {
+ return m_context;
+ }
+
+
+ @SuppressWarnings("all")
+ public ServiceReference registerService( String[] ifaces, Object impl, Properties props )
+ {
+
+ ServiceReference ref = createReference( ifaces, props );
+
+ Mockito.when( m_context.registerService( ifaces, impl, props ) )
+ .thenReturn( null );
+
+ Mockito.when( m_context.getService( ref ) ).thenReturn( impl );
+
+ m_references.put( impl, ref );
+
+ return ref;
+ }
+
+
+ public ServiceReference getReference( Object service )
+ {
+ return m_references.get( service );
+ }
+
+
+ public Bundle getBundle( ServiceReference ref )
+ {
+ return m_bundles.get( ref );
+ }
+
+
+
+ @SuppressWarnings("all")
+ public ServiceReference createReference( String[] ifaces, Properties props )
+ {
+
+ final ServiceReference ref = Mockito.mock( ServiceReference.class );
+
+ RefPropAnswer answer = new RefPropAnswer( props, ifaces );
+
+ Mockito.when( ref.getProperty( Mockito.anyString() ) )
+ .thenAnswer( answer );
+
+ Mockito.when( ref.getPropertyKeys() )
+ .thenReturn( props.keySet().toArray( new String[0] ) );
+
+ Bundle bundle = Mockito.mock( Bundle.class );
+
+ Mockito.when( ref.getBundle() ).thenReturn( bundle );
+
+ m_bundles.put( ref, bundle );
+
+ return ref;
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private class RefPropAnswer implements Answer<Object>
+ {
+ private final Dictionary m_p;
+
+
+ public RefPropAnswer( Dictionary p, String[] iface )
+ {
+ m_p = p;
+ m_p.put( Constants.OBJECTCLASS, iface );
+ m_p.put( Constants.SERVICE_ID, m_serviceIndex++ );
+ }
+
+
+ public Object answer(InvocationOnMock invocation) throws Throwable
+ {
+ String key = (String)invocation.getArguments()[0];
+ return m_p.get( key );
+ }
+
+ }
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/Utils.java b/deviceaccess/src/test/java/org/apache/felix/das/Utils.java
new file mode 100644
index 0000000..9398e13
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/Utils.java
@@ -0,0 +1,78 @@
+/*
+ * 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.das;
+
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+
+/**
+ * Utility class for injecting objects and invoking
+ * methods that are normally invoked by the dependency manager.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ *
+ */
+public class Utils
+{
+
+ public static void invoke( Object target, String method )
+ {
+ try
+ {
+ Method m = target.getClass().getDeclaredMethod( method, new Class[0] );
+ m.setAccessible( true );
+ m.invoke( target, new Object[0] );
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace();
+ junit.framework.Assert.fail( e.getMessage() );
+ }
+ }
+
+
+ public static void inject( Object target, Class<?> clazz, Object injectable )
+ {
+
+ Field[] fields = target.getClass().getDeclaredFields();
+
+ for ( Field field : fields )
+ {
+ if ( clazz == field.getType() )
+ {
+ field.setAccessible( true );
+ try
+ {
+ field.set( target, injectable );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ e.printStackTrace();
+ }
+ catch ( IllegalAccessException e )
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/util/DriverAnalyzerTest.java b/deviceaccess/src/test/java/org/apache/felix/das/util/DriverAnalyzerTest.java
new file mode 100644
index 0000000..e44c37e
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/util/DriverAnalyzerTest.java
@@ -0,0 +1,113 @@
+package org.apache.felix.das.util;
+
+
+import java.util.Properties;
+
+import org.apache.felix.das.OSGiMock;
+import org.apache.felix.das.Utils;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.device.Constants;
+import org.osgi.service.device.Driver;
+import org.osgi.service.log.LogService;
+
+
+/**
+ *
+ * Tests the Driver Analyzer.
+ *
+ * Nothing fancy is being tested, but if something is changed this
+ * validates that at least the most basic feedback can be expected.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ *
+ */
+public class DriverAnalyzerTest {
+
+
+
+ private DriverAnalyzer m_analyzer;
+
+
+ @Mock
+ private LogService m_log;
+
+ private OSGiMock m_osgi;
+
+ @Before
+ public void setUp() throws Exception {
+
+ MockitoAnnotations.initMocks(this);
+
+ m_osgi = new OSGiMock();
+ m_analyzer = new DriverAnalyzer();
+
+ Utils.inject(m_analyzer, LogService.class, m_log);
+ }
+
+
+ @Test
+ public void VerifyCorrectDriverIsIgnored() {
+
+
+ Properties p = new Properties();
+ p.put(Constants.DRIVER_ID, "a-driver-id");
+
+
+ ServiceReference ref = m_osgi.createReference(new String[]{Driver.class.getName()}, p);
+
+ m_analyzer.driverAdded(ref);
+
+ Mockito.verifyZeroInteractions(m_log);
+
+ }
+
+ @Test
+ public void VerifyIncorrectDriverNoDriverId() {
+
+
+ Properties p = new Properties();
+
+ ServiceReference ref = m_osgi.createReference(new String[]{Driver.class.getName()}, p);
+
+ m_analyzer.driverAdded(ref);
+
+ Mockito.verify(m_log).log(Mockito.eq(LogService.LOG_ERROR), Mockito.anyString());
+ Mockito.verifyNoMoreInteractions(m_log);
+
+ }
+
+ @Test
+ public void VerifyIncorrectDriverInvalidDriverId() {
+
+ Properties p = new Properties();
+ p.put(Constants.DRIVER_ID, new Object());
+
+ ServiceReference ref = m_osgi.createReference(new String[]{Driver.class.getName()}, p);
+
+ m_analyzer.driverAdded(ref);
+
+ Mockito.verify(m_log).log(Mockito.eq(LogService.LOG_ERROR), Mockito.anyString());
+ Mockito.verifyNoMoreInteractions(m_log);
+
+ }
+
+ @Test
+ public void VerifyIncorrectDriverEmptyDriverId() {
+
+ Properties p = new Properties();
+ p.put(Constants.DRIVER_ID, "");
+
+ ServiceReference ref = m_osgi.createReference(new String[]{Driver.class.getName()}, p);
+
+ m_analyzer.driverAdded(ref);
+
+ Mockito.verify(m_log).log(Mockito.eq(LogService.LOG_ERROR), Mockito.anyString());
+ Mockito.verifyNoMoreInteractions(m_log);
+
+ }
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/util/DriverLoaderTest.java b/deviceaccess/src/test/java/org/apache/felix/das/util/DriverLoaderTest.java
new file mode 100644
index 0000000..789e2dd
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/util/DriverLoaderTest.java
@@ -0,0 +1,262 @@
+/*
+ * 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.das.util;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.das.DeviceManager;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.device.Constants;
+import org.osgi.service.device.DriverLocator;
+
+
+/**
+ * The Device Manager delegates driver loading to the DriverLoader.
+ * This JUnit test tests the behavior of that DriverMatcher.
+ *
+ * Tests all kinds of driver loading flows.
+ * all flows pertaining driver loading are grouped in the DriverLoader.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ *
+ */
+public class DriverLoaderTest
+{
+
+
+ private DriverLoader m_loader;
+
+ @Mock
+ private BundleContext m_context;
+
+ @Mock
+ private DeviceManager m_log;
+
+ @Before
+ public void setUp() throws Exception
+ {
+
+ MockitoAnnotations.initMocks(this);
+ m_loader = new DriverLoader( m_log, m_context );
+ }
+
+
+ private DriverLocator tstExpectDriverIdsFor(String[] ids) {
+
+ DriverLocator dl = Mockito.mock(DriverLocator.class );
+ Mockito.when( dl.findDrivers( Mockito.isA(Dictionary.class) ) ).thenReturn( ids );
+ return dl;
+ }
+
+ /**
+ * test whether the driver loader can handle a situation where
+ * there are no DriverLocators.
+ *
+ */
+ @Test
+ public void findDriversNoDriverLocators()
+ {
+
+ List<DriverLocator> locators = new ArrayList<DriverLocator>();
+
+
+ List<String> driverIds = m_loader.findDrivers( locators, new Properties() );
+ Assert.assertTrue( "should be an empty list", driverIds.size() == 0 );
+
+ }
+
+
+ /**
+ * in this test there is a driver locator. the driver locator is instructed to
+ * even return some driver ids.
+ * this test tests whether these driver ids are really returned.
+ */
+ @Test
+ public void findDriversWithDriverLocator()
+ {
+
+ List<DriverLocator> locators = new ArrayList<DriverLocator>();
+
+ DriverLocator dl = tstExpectDriverIdsFor(
+ new String[] { "org.apache.felix.driver-1.0", "org.apache.felix.driver-1.1" } );
+
+ locators.add( dl );
+
+ Properties dict = new Properties();
+ List<String> driverIds = m_loader.findDrivers( locators, dict );
+
+ Assert.assertEquals( "should not be an empty list", 2, driverIds.size());
+
+ }
+
+
+ /**
+ * in this test there are several driver locators, some of which return
+ * driver Ids, some don't. we expect an accurate number of driver ids being returned
+ * from the driverloader.
+ */
+ @Test
+ public void findDriversWithDriverLocators()
+ {
+
+ List<DriverLocator> locators = new ArrayList<DriverLocator>();
+
+ DriverLocator dl1 = tstExpectDriverIdsFor(
+ new String[]{ "org.apache.felix.driver-1.0", "org.apache.felix.driver-1.1" } );
+ locators.add( dl1 );
+
+ DriverLocator dl2 = tstExpectDriverIdsFor(
+ new String[]{ "org.apache.felix.driver-1.2", "org.apache.felix.driver-1.3" } );
+ locators.add( dl2 );
+
+ DriverLocator dl3 = tstExpectDriverIdsFor( null );
+ locators.add( dl3 );
+
+
+ Properties dict = new Properties();
+ List<String> driverIds = m_loader.findDrivers( locators, dict );
+
+ Assert.assertEquals( "should not be an empty list", 4, driverIds.size() );
+
+ }
+
+
+ @Test
+ public void findDriversWithDriverLocatorFails()
+ {
+
+ Properties dict = new Properties();
+ List<DriverLocator> locators = new ArrayList<DriverLocator>();
+
+ DriverLocator dl = Mockito.mock( DriverLocator.class, "dl" );
+ locators.add( dl );
+
+ Mockito.when( dl.findDrivers( Mockito.eq( dict ) ) ).thenThrow( new RuntimeException( "test exception" ) );
+
+ List<String> driverIds = m_loader.findDrivers( locators, dict );
+
+ Assert.assertTrue( "should be an empty list", driverIds.size() == 0 );
+
+ }
+
+
+ @Test
+ public void loadDrivers() throws IOException, BundleException
+ {
+
+ List<DriverLocator> locators = new ArrayList<DriverLocator>();
+
+ DriverLocator dl = Mockito.mock( DriverLocator.class, "dl" );
+ locators.add( dl );
+
+ String[] driverIds = new String[]
+ { "org.apache.felix.driver-1.0", "org.apache.felix.driver-1.1", };
+
+ for ( String string : driverIds )
+ {
+ Mockito.when( dl.loadDriver( Mockito.eq( string ) ) ).thenReturn( null );
+ Bundle bundle = Mockito.mock( Bundle.class );
+
+ Mockito.when( m_context.installBundle( "_DD_" + string, null ) ).thenReturn( bundle );
+ bundle.start();
+
+ ServiceReference ref = Mockito.mock( ServiceReference.class );
+ Mockito.when( ref.getProperty( Constants.DRIVER_ID ) ).thenReturn( string );
+ Mockito.when( bundle.getRegisteredServices() ).thenReturn( new ServiceReference[]
+ { ref } );
+ }
+
+ List<ServiceReference> refs = m_loader.loadDrivers( locators, driverIds );
+
+ Assert.assertEquals( "", 2, refs.size() );
+ for ( ServiceReference serviceReference : refs )
+ {
+ String driverId = "" + serviceReference.getProperty( Constants.DRIVER_ID );
+ if ( !driverId.equals( driverIds[0] ) && !driverId.equals( driverIds[1] ) )
+ {
+ Assert.fail( "unexpected driverId" );
+ }
+ }
+
+ }
+
+
+ @Test
+ public void loadDrivers_LoadFails() throws IOException, BundleException
+ {
+
+ List<DriverLocator> locators = new ArrayList<DriverLocator>();
+
+ DriverLocator dl = Mockito.mock( DriverLocator.class, "dl" );
+ locators.add( dl );
+
+ String[] driverIds = new String[]
+ { "org.apache.felix.driver-1.0", "org.apache.felix.driver-1.1", };
+
+ for ( String string : driverIds )
+ {
+ Mockito.when( dl.loadDriver( string ) ).thenThrow( new IOException( "test exception" ) );
+ }
+
+ List<ServiceReference> refs = m_loader.loadDrivers( locators, driverIds );
+
+ Assert.assertEquals( "", 0, refs.size() );
+
+ }
+
+
+ @Test
+ public void loadDrivers_InstallFails() throws IOException, BundleException
+ {
+
+ List<DriverLocator> locators = new ArrayList<DriverLocator>();
+
+ DriverLocator dl = Mockito.mock( DriverLocator.class, "dl" );
+ locators.add( dl );
+
+ String[] driverIds = new String[]
+ { "org.apache.felix.driver-1.0", "org.apache.felix.driver-1.1", };
+
+ for ( String string : driverIds )
+ {
+ Mockito.when( dl.loadDriver( string ) ).thenReturn( null );
+ Mockito.when( m_context.installBundle( DriverLoader.DRIVER_LOCATION_PREFIX + string, null ) )
+ .thenThrow(new BundleException( "test exception" ) );
+ }
+
+ List<ServiceReference> refs = m_loader.loadDrivers( locators, driverIds );
+
+ Assert.assertEquals( "", 0, refs.size() );
+ }
+
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/util/DriverMatcherTest.java b/deviceaccess/src/test/java/org/apache/felix/das/util/DriverMatcherTest.java
new file mode 100644
index 0000000..c020d7e
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/util/DriverMatcherTest.java
@@ -0,0 +1,329 @@
+/*
+ * 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.das.util;
+
+
+
+import org.apache.felix.das.DriverAttributes;
+import org.apache.felix.das.DeviceManager;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.device.Driver;
+import org.osgi.service.device.DriverSelector;
+import org.osgi.service.device.Match;
+
+
+/**
+ * The Device Manager delegates driver matching to the DriverMatcher.
+ * This JUnit test tests the behavior of that DriverMatcher.
+ *
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DriverMatcherTest
+{
+
+ private DriverMatcher m_matcherImpl;
+
+ private int m_serviceId;
+
+ @Mock
+ private DeviceManager m_log;
+
+ @Before
+ public void setUp() throws Exception
+ {
+
+ m_serviceId = 0;
+
+ MockitoAnnotations.initMocks(this);
+
+ m_matcherImpl = new DriverMatcher( m_log );
+
+ }
+
+
+ private String tstDriverId( Match match )
+ {
+ return ( String ) match.getDriver().getProperty( org.osgi.service.device.Constants.DRIVER_ID );
+ }
+
+
+ private DriverAttributes tstCreateDriverAttributes( String id, int match, int ranking ) throws Exception
+ {
+
+ Bundle bundle = Mockito.mock( Bundle.class );
+ ServiceReference ref = Mockito.mock( ServiceReference.class );
+
+
+ Mockito.when(ref.getBundle()).thenReturn(bundle);
+ Mockito.when(bundle.getLocation()).thenReturn(DriverLoader.DRIVER_LOCATION_PREFIX + "-" + id);
+
+ Mockito.when(ref.getProperty(Constants.SERVICE_ID))
+ .thenReturn(m_serviceId++);
+
+ Mockito.when(ref.getProperty(org.osgi.service.device.Constants.DRIVER_ID))
+ .thenReturn(id);
+
+
+
+ if ( ranking > 0 )
+ {
+ Mockito.when( ref.getProperty( Constants.SERVICE_RANKING ) ).thenReturn( ranking );
+ }
+ else if ( ranking == 0 )
+ {
+ Mockito.when( ref.getProperty( Constants.SERVICE_RANKING ) ).thenReturn( null );
+ }
+ else
+ {
+ //an invalid ranking object
+ Mockito.when( ref.getProperty( Constants.SERVICE_RANKING ) ).thenReturn( new Object() );
+ }
+
+ Driver driver = Mockito.mock( Driver.class );
+ Mockito.when( driver.match( Mockito.isA( ServiceReference.class ) ) ).thenReturn( match );
+
+ return new DriverAttributes( ref, driver );
+
+ }
+
+
+ private void add( String id, int match ) throws Exception
+ {
+ add( id, match, 0 );
+ }
+
+
+ private void add( String id, int match, int ranking ) throws Exception
+ {
+ m_matcherImpl.add( match, tstCreateDriverAttributes( id, match, ranking ) );
+ }
+
+
+ @Test
+ public void GetBestMatchWithNoDriver() throws Exception
+ {
+
+ Match match = m_matcherImpl.getBestMatch();
+ Assert.assertNull( match );
+
+ }
+
+
+ @Test
+ public void GetBestMatchWithOneDriver() throws Exception
+ {
+
+ add( "org.apache.felix.driver-1.0", 1 );
+
+ Match match = m_matcherImpl.getBestMatch();
+ Assert.assertNotNull( match );
+ Assert.assertEquals( "org.apache.felix.driver-1.0", tstDriverId( match ) );
+
+ }
+
+
+ @Test
+ public void GetSelectBestMatchThrowsException() throws Exception
+ {
+
+ ServiceReference deviceRef = Mockito.mock(ServiceReference.class);
+ DriverSelector selector = Mockito.mock(DriverSelector.class);
+
+ Mockito.when(selector.select(Mockito.eq(deviceRef), Mockito.isA(Match[].class)))
+ .thenThrow(new IllegalArgumentException("test"));
+
+ Match match = m_matcherImpl.selectBestMatch(deviceRef, selector);
+ Assert.assertNull( match );
+
+ }
+
+ @Test
+ public void GetBestMatchWithMultipleDrivers() throws Exception
+ {
+
+ add( "org.apache.felix.driver.a-1.0", 1 );
+ add( "org.apache.felix.driver.b-1.0", 1 );
+ add( "org.apache.felix.driver.c-1.0", 10 );
+
+ Match match = m_matcherImpl.getBestMatch();
+ Assert.assertNotNull( match );
+ Assert.assertEquals( "org.apache.felix.driver.c-1.0", tstDriverId( match ) );
+
+ }
+
+
+ @Test
+ public void GetBestMatchWithInvalidRanking() throws Exception
+ {
+
+ add( "org.apache.felix.driver.a-1.0", 1, 0 );
+ add( "org.apache.felix.driver.b-1.0", 1, -1 );
+
+ Match match = m_matcherImpl.getBestMatch();
+ Assert.assertNotNull( match );
+ Assert.assertEquals( "org.apache.felix.driver.a-1.0", tstDriverId( match ) );
+
+ }
+
+
+ @Test
+ public void GetBestMatchWithSameRanking() throws Exception
+ {
+
+ add( "org.apache.felix.driver.a-1.0", 1 );
+ add( "org.apache.felix.driver.b-1.0", 1 );
+
+ Match match = m_matcherImpl.getBestMatch();
+ Assert.assertNotNull( match );
+ Assert.assertEquals( "org.apache.felix.driver.a-1.0", tstDriverId( match ) );
+ Assert.assertEquals( 1, match.getMatchValue() );
+ }
+
+
+ @Test
+ public void GetBestMatchWithDifferentRanking() throws Exception
+ {
+
+ add( "org.apache.felix.driver.a-1.0", 1, 2 );
+ add( "org.apache.felix.driver.b-1.0", 1 );
+
+ Match match = m_matcherImpl.getBestMatch();
+
+ Assert.assertNotNull( match );
+ final String driverId = "org.apache.felix.driver.a-1.0";
+
+ Assert.assertEquals( driverId, tstDriverId( match ) );
+ Assert.assertEquals( 1, match.getMatchValue() );
+ }
+
+
+ @Test
+ public void GetBestMatchWithDifferentMatchValue() throws Exception
+ {
+
+ add( "org.apache.felix.driver.a-1.0", 1 );
+ add( "org.apache.felix.driver.b-1.0", 2 );
+ add( "org.apache.felix.driver.c-1.0", 1 );
+
+ Match match = m_matcherImpl.getBestMatch();
+ Assert.assertNotNull( match );
+ Assert.assertEquals( "org.apache.felix.driver.b-1.0", tstDriverId( match ) );
+
+ Assert.assertEquals( 2, match.getMatchValue() );
+ }
+
+
+ @Test
+ public void selectBestDriver() throws Exception
+ {
+
+ DriverSelector selector = Mockito.mock( DriverSelector.class );
+ ServiceReference deviceRef = Mockito.mock( ServiceReference.class );
+
+ add( "org.apache.felix.driver-1.0", 1 );
+ add( "org.apache.felix.driver-1.1", 1 );
+ add( "org.apache.felix.driver-1.2", 1 );
+ add( "org.apache.felix.driver-1.3", 1 );
+ add( "org.apache.felix.driver-1.4", 1 );
+ add( "org.apache.felix.driver-1.5", 1 );
+
+
+
+ //this is the actual driverselector implementation
+ Mockito.when( selector.select( Mockito.isA(ServiceReference.class), Mockito.isA(Match[].class) ) )
+ .thenAnswer( new Answer<Integer>()
+ {
+
+ public Integer answer(InvocationOnMock invocation) throws Throwable
+ {
+ Match[] matches = ( Match[] ) invocation.getArguments()[1];
+ int index = 0;
+ for ( Match m : matches )
+ {
+ if ( tstDriverId( m ).endsWith( "1.3" ) )
+ {
+ return index;
+ }
+ index++;
+ }
+ Assert.fail( "expected unreachable" );
+ return null;
+ }
+ } );
+
+
+ Match match = m_matcherImpl.selectBestMatch( deviceRef, selector );
+
+ Assert.assertNotNull( "no match returned", match );
+ String driverId = tstDriverId( match );
+
+ Assert.assertEquals( "org.apache.felix.driver-1.3", driverId );
+ }
+
+
+ @Test
+ public void selectFails() throws Exception
+ {
+
+ DriverSelector selector = Mockito.mock( DriverSelector.class );
+ ServiceReference deviceRef = Mockito.mock( ServiceReference.class );
+
+ Mockito.when( selector.select( Mockito.eq( deviceRef ), Mockito.isA(Match[].class) ) )
+ .thenThrow( new RuntimeException( "test exception" ) );
+
+ add( "org.apache.felix.driver-1.5", 1 );
+
+ Match match = m_matcherImpl.selectBestMatch( deviceRef, selector );
+
+ Assert.assertNull( match );
+
+ }
+
+
+ @Test
+ public void VerifyMatchToString() throws Exception
+ {
+
+ DriverSelector selector = Mockito.mock( DriverSelector.class );
+ ServiceReference deviceRef = Mockito.mock( ServiceReference.class );
+
+ Mockito.when( selector.select( Mockito.eq( deviceRef ), Mockito.isA(Match[].class) ) )
+ .thenReturn( 0 );
+
+ add( "org.apache.felix.driver-1.5", 2 );
+
+ Match match = m_matcherImpl.selectBestMatch( deviceRef, selector );
+
+ Assert.assertNotNull( match );
+ Assert.assertNotNull( match.toString() );
+
+ }
+
+}
diff --git a/deviceaccess/src/test/java/org/apache/felix/das/util/UtilTest.java b/deviceaccess/src/test/java/org/apache/felix/das/util/UtilTest.java
new file mode 100644
index 0000000..c19a690
--- /dev/null
+++ b/deviceaccess/src/test/java/org/apache/felix/das/util/UtilTest.java
@@ -0,0 +1,220 @@
+/*
+ * 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.das.util;
+
+
+import java.util.Properties;
+
+import junit.framework.Assert;
+
+import org.apache.felix.das.Utils;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.device.Constants;
+import org.osgi.service.device.Device;
+import org.osgi.service.log.LogService;
+
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ *
+ */
+public class UtilTest
+{
+
+ private DeviceAnalyzer m_devA;
+
+ @Mock
+ private LogService m_log;
+
+ @Mock
+ private BundleContext m_context;
+
+
+ @Before
+ public void before() throws Exception
+ {
+
+ MockitoAnnotations.initMocks(this);
+
+ m_devA = new DeviceAnalyzer( m_context );
+ Utils.inject( m_devA, LogService.class, m_log );
+
+
+ String f1 = "(objectClass=org.osgi.service.device.Device)";
+ Filter deviceFilter = FrameworkUtil.createFilter(f1);
+ Mockito.when(m_context.createFilter(Mockito.eq(f1))).thenReturn(deviceFilter);
+
+ String f2 = "(DEVICE_CATEGORY=*)";
+ Filter driverFilter = FrameworkUtil.createFilter(f2);
+ Mockito.when(m_context.createFilter(f2)).thenReturn(driverFilter);
+
+
+ Utils.invoke( m_devA, "start" );
+ }
+
+
+
+ private ServiceReference createReference(final Properties p)
+ {
+ ServiceReference ref = Mockito.mock( ServiceReference.class );
+
+ Mockito.when(ref.getProperty(Mockito.anyString())).thenAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return p.get(invocation.getArguments()[0].toString());
+ }
+ });
+
+ Mockito.when(ref.getPropertyKeys()).thenAnswer(new Answer<Object>() {
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return p.keySet().toArray(new String[0]);
+ }
+ });
+
+
+ return ref;
+ }
+
+ @Test
+ public void ShowDeviceIfThereIsAnInvalidCategory() throws Exception
+ {
+
+ Properties p = new Properties();
+ p.put( org.osgi.framework.Constants.OBJECTCLASS, new String[]{Object.class.getName()} );
+ p.put(Constants.DEVICE_CATEGORY, "dummy");
+
+ ServiceReference ref = createReference(p);
+
+ m_devA.deviceAdded( ref );
+
+ Mockito.verify(m_log).log(Mockito.eq(LogService.LOG_ERROR), Mockito.anyString());
+
+ }
+
+
+ @Test
+ public void ShowDeviceIfThereIsNoCategory() throws Exception
+ {
+
+ Properties p = new Properties();
+ p.put( org.osgi.framework.Constants.OBJECTCLASS, new String[]{Object.class.getName()} );
+
+ ServiceReference ref = createReference(p);
+
+ m_devA.deviceAdded( ref );
+
+ Mockito.verify(m_log).log( Mockito.eq( LogService.LOG_ERROR ), Mockito.isA( String.class ) );
+ }
+
+ @Test
+ public void VerifyValidIsDeviceInstanceValidationIfDevice() throws InvalidSyntaxException
+ {
+
+ Properties p = new Properties();
+ p.put( org.osgi.framework.Constants.OBJECTCLASS, new String[]{Device.class.getName()} );
+
+ ServiceReference ref = createReference(p);
+
+ Assert.assertTrue( "Incorrectly determined as no device", Util.isDeviceInstance(ref) );
+ }
+
+ @Test
+ public void VerifyValidIsDeviceInstanceValidationThrowsException() throws InvalidSyntaxException
+ {
+
+ Properties p = new Properties();
+ p.put( org.osgi.framework.Constants.OBJECTCLASS, new String[]{Device.class.getName()} );
+
+ ServiceReference ref = createReference(p);
+
+ Assert.assertTrue( "Incorrectly determined as no device", Util.isDeviceInstance(ref) );
+ }
+
+ @Test
+ public void VerifyValidFilterStringCreation() throws InvalidSyntaxException {
+
+ Object[] data = new Object[]{"a","b","c","d"};
+ String str = Util.createFilterString("(|(%s=%s)(%s=%s))", data);
+
+ Assert.assertEquals("filter string mismatch","(|(a=b)(c=d))", str);
+ }
+
+ @Test
+ public void VerifyValidFilterCreation() throws InvalidSyntaxException {
+
+ Object[] data = new Object[]{Constants.DEVICE_CATEGORY, "dummy"};
+ Filter filter = Util.createFilter("(%s=%s)", data);
+
+
+ Properties matching = new Properties();
+ matching.put(Constants.DEVICE_CATEGORY, new String[]{"dummy", "nonsense"});
+ Assert.assertTrue("matching filter does not match", filter.match(matching));
+
+ Properties notmatching = new Properties();
+ notmatching.put(Constants.DEVICE_CATEGORY, new String[]{"lummy", "nonsense"});
+ Assert.assertFalse("notmatching filter does match", filter.match(notmatching));
+
+
+ }
+
+
+
+
+
+ @Test
+ public void ShowDeviceIfThereIsAnEmptyCategory() throws Exception
+ {
+
+ Properties p = new Properties();
+ p.put( org.osgi.framework.Constants.OBJECTCLASS, new String[]{Object.class.getName()} );
+ p.put( Constants.DEVICE_CATEGORY, new String[0] );
+
+
+ ServiceReference ref = createReference(p);
+
+ m_devA.deviceAdded( ref );
+
+ Mockito.verify(m_log).log( Mockito.eq( LogService.LOG_ERROR ), Mockito.isA( String.class ) );
+
+ }
+
+
+ @Test
+ public void NoShowDeviceIfThereIsAValidCategory() throws Exception
+ {
+
+ Properties p = new Properties();
+ p.put( org.osgi.framework.Constants.OBJECTCLASS, new String[]{Device.class.getName()} );
+ p.put( Constants.DEVICE_CATEGORY, new String[]{"dummy"} );
+
+ ServiceReference ref = createReference(p);
+
+ m_devA.deviceAdded( ref );
+ }
+}