blob: 35ee49618c57779471c02073c4b3bd90ee06b7f9 [file] [log] [blame]
Stuart McCulloch798b4562009-04-16 09:32:05 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.das;
20
21
22import java.io.IOException;
23import java.io.InputStream;
24import java.util.Dictionary;
25import java.util.HashMap;
26import java.util.Map;
27import java.util.Properties;
28import java.util.concurrent.CountDownLatch;
29import java.util.concurrent.TimeUnit;
30
31import junit.framework.Assert;
32
33import org.apache.felix.das.util.DriverLoader;
34import org.junit.After;
35import org.junit.Before;
36import org.junit.Ignore;
37import org.junit.Test;
38import org.mockito.Mock;
39import org.mockito.Mockito;
40import org.mockito.MockitoAnnotations;
41import org.mockito.invocation.InvocationOnMock;
42import org.mockito.stubbing.Answer;
43import org.osgi.framework.Bundle;
44import org.osgi.framework.BundleContext;
45import org.osgi.framework.BundleException;
46import org.osgi.framework.ServiceReference;
47import org.osgi.service.device.Constants;
48import org.osgi.service.device.Device;
49import org.osgi.service.device.Driver;
50import org.osgi.service.device.DriverLocator;
51import org.osgi.service.device.DriverSelector;
52import org.osgi.service.device.Match;
53import org.osgi.service.log.LogService;
54
55
56
57/**
58 * Test the actual implementation.
59 *
60 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
61 */
62public class DeviceManagerTest
63{
64
65 @Mock
66 private DeviceManager m_manager;
67
68 @Mock Bundle m_systemBundle;
69
70 @Mock
71 private LogService m_log;
72
73
74 private BundleContext m_context;
75
76
77 private OSGiMock m_osgi;
78
79
80 @Before
81 public void setUp() throws Exception
82 {
83 m_osgi = new OSGiMock();
84
85 MockitoAnnotations.initMocks(this);
86
87 m_context = m_osgi.getBundleContext();
88
89 m_manager = new DeviceManager( m_context );
90
91 Utils.invoke( m_manager, "init" );
92
93 Utils.inject( m_manager, LogService.class, m_log );
94
95 Mockito.when( m_context.getBundle( 0 ) ).thenReturn( m_systemBundle );
96
97 final CountDownLatch latch = new CountDownLatch( 1 );
98
99 Answer<Integer> answer = new Answer<Integer>()
100 {
101 public Integer answer(InvocationOnMock invocation) throws Throwable
102 {
103 latch.countDown();
104 return Bundle.ACTIVE;
105 }
106 };
107
108 Mockito.when( m_systemBundle.getState() ).thenAnswer( answer );
109
110 Utils.invoke( m_manager, "start" );
111 latch.await( 5, TimeUnit.SECONDS );
112
113 Mockito.when( m_context.installBundle(Mockito.isA( String.class ), ( InputStream ) Mockito.isNull() ) )
114 .thenThrow(new NullPointerException( "inputstream is null exception" ) );
115 }
116
117
118 @After
119 public void tearDown() throws Exception
120 {
121 Utils.invoke( m_manager, "stop" );
122 Utils.invoke( m_manager, "destroy" );
123 }
124
125 private Driver tstCreateDriver( String driverId, int match ) throws Exception
126 {
127 Properties p = new Properties();
128 p.put( Constants.DRIVER_ID, driverId );
129 p.put( "match", Integer.toString( match ) );
130
131 return tstCreateDriver( p );
132 }
133
134
135 private Driver tstCreateDriver( Properties p ) throws Exception
136 {
137 Driver driver = Mockito.mock( Driver.class );
138
139 ServiceReference ref = m_osgi.registerService(
140 new String[]{ Driver.class.getName() }, driver, p );
141
142 MatchAnswer answer = new MatchAnswer( ref );
143
144 Mockito.when( driver.match( Mockito.isA( ServiceReference.class ) ) )
145 .thenAnswer( answer );
146
147 Bundle bundle = m_osgi.getBundle( ref );
148 Mockito.when( bundle.getLocation() )
149 .thenReturn(
150 DriverLoader.DRIVER_LOCATION_PREFIX + p.getProperty( Constants.DRIVER_ID ));
151
152 return driver;
153 }
154
155
156 private Device tstCreateDevice( String[] cat )
157 {
158 return tstCreateDevice( cat, true );
159 }
160
161
162 private Device tstCreateDevice( String[] cat, boolean isDevice )
163 {
164 Properties p = new Properties();
165 p.put( Constants.DEVICE_CATEGORY, cat );
166 if ( isDevice )
167 {
168 return ( Device ) tstCreateService( p, Device.class );
169 }
170 return tstCreateService( p, Object.class );
171 }
172
173
174 @SuppressWarnings("unchecked")
175 private <T> T tstCreateService( Properties p, Class<?> iface )
176 {
177 T svc = ( T ) Mockito.mock( iface, iface.getSimpleName() );
178
179 m_osgi.registerService( new String[]
180 { iface.getName() }, svc, p );
181 return svc;
182 }
183
184
185 /**
186 *
187 * prepared all expected behavior for the installation of a dynamic driver
188 * bundle based on an acquired InputStream.
189 *
190 *
191 * @param driverId
192 * @param match
193 * @param in
194 * @return
195 * @throws BundleException
196 * @throws Exception
197 */
198 private Driver tstExpectInstallDriverBundle( String driverId, int match, InputStream in ) throws BundleException,
199 Exception
200 {
201
202 Bundle bundle = Mockito.mock( Bundle.class, "driverBundle" );
203 Mockito.when( m_context.installBundle(
204 Mockito.eq( "_DD_" + driverId ), Mockito.eq( in ) ) )
205 .thenReturn( bundle );
206
207 final Driver driver = tstCreateDriver( driverId, match );
208 final ServiceReference driverRef = m_osgi.getReference( driver );
209
210 Answer<Object> answer = new Answer<Object>()
211 {
212
213 public Object answer(InvocationOnMock invocation) throws Throwable
214 {
215 m_manager.driverAdded( driverRef, driver );
216 return null;
217 }
218 };
219
220 //bundle start leads to the addition of the driver to
221 //the device manager.
222 Mockito.doAnswer(answer).when(bundle).start();
223
224 Mockito.when( bundle.getRegisteredServices() )
225 .thenReturn( new ServiceReference[]{ driverRef } );
226
227 return driver;
228 }
229
230
231 /**
232 * returns a CountDownLatch.
233 * This countdown latch will count down as soon as <code>Device.noDriverFound()</code>
234 * has been called.
235 * @param device the Device
236 * @return the countdown latch
237 */
238 private CountDownLatch tstExpectNoDriverFound( Device device )
239 {
240 final CountDownLatch latch = new CountDownLatch( 1 );
241
242 //countdown when noDriverFound is called
243 Answer<Object> answer = new Answer<Object>()
244 {
245 public Object answer(InvocationOnMock invocation) throws Throwable
246 {
247 latch.countDown();
248 return null;
249 }
250 };
251
252 Mockito.doAnswer( answer ).when(device).noDriverFound();
253
254 return latch;
255
256 }
257
258
259 private CountDownLatch tstExpectAttach( Driver driver, Object device ) throws Exception
260 {
261 final CountDownLatch latch = new CountDownLatch( 1 );
262 Answer<String> answer = new Answer<String>()
263 {
264 public String answer(InvocationOnMock invocation) throws Throwable
265 {
266 latch.countDown();
267 return null;
268 }
269 };
270
271 //successful attach
272 Mockito.when( driver.attach( m_osgi.getReference( device ) ) )
273 .thenAnswer( answer );
274
275 return latch;
276 }
277
278 private CountDownLatch tstExpectUnloadDriverBundle( Driver driver ) throws BundleException {
279
280
281 final CountDownLatch latch = new CountDownLatch( 1 );
282 Answer<String> answer = new Answer<String>()
283 {
284 public String answer(InvocationOnMock invocation) throws Throwable
285 {
286 latch.countDown();
287 return null;
288 }
289 };
290
291 Bundle bundle = m_osgi.getBundle( m_osgi.getReference( driver ) );
292
293 Mockito.doAnswer(answer).when( bundle ).uninstall();
294
295 return latch;
296 }
297
298 /**
299 * This method generates behavior on the provided DriverLocator.
300 *
301 * The given driver Ids and their matches are expected as drivers found
302 * by this driver locator.
303 * Also, if a driver is found, we can also expect that loadDriver is called;
304 * resulting in an InputStream. That particular input stream should, when installed
305 * using a bundle context, lead to the registration of a driver with
306 * the correcsponding driver id.
307 *
308 * @param locator
309 * @param driverIds
310 * @param matches
311 * @return
312 * @throws Exception
313 */
314 private Map<String, Driver> tstExpectDriverLocatorFor( final DriverLocator locator, final String[] driverIds,
315 int[] matches ) throws Exception
316 {
317
318 Mockito.when( locator.findDrivers( Mockito.isA( Dictionary.class ) ) )
319 .thenReturn( driverIds );
320
321 Map<String, Driver> drivers = new HashMap<String, Driver>();
322
323 final Map<String, InputStream> streams = new HashMap<String, InputStream>();
324
325 for ( String driverId : driverIds )
326 {
327 InputStream in = Mockito.mock(InputStream.class, "[InputStream for: " + driverId + "]");
328 streams.put( driverId, in );
329 }
330
331 Answer<InputStream> answer = new Answer<InputStream>()
332 {
333 public InputStream answer(InvocationOnMock invocation) throws Throwable
334 {
335 final String id = invocation.getArguments()[0].toString();
336
337 for ( String driverId : driverIds )
338 {
339 if ( id.equals( driverId ) )
340 {
341 return streams.get( id );
342 }
343 }
344 throw new IOException( "no such driverId defined in this locator: " + locator );
345 }
346 };
347
348
349 Mockito.when( locator.loadDriver( Mockito.isA( String.class ) ) )
350 .thenAnswer( answer );
351
352 int i = 0;
353 for ( String driverId : driverIds )
354 {
355 Driver driver = tstExpectInstallDriverBundle( driverId, matches[i], streams.get( driverId ) );
356 drivers.put( driverId, driver );
357 i++;
358 }
359
360 return drivers;
361
362 }
363
364
365 /**
366 * does not really test anything special, but ensures that the internal
367 * structure is able to parse the addition
368 */
369 @Test
370 public void LocatorAdded()
371 {
372
373 DriverLocator locator = Mockito.mock( DriverLocator.class );
374 m_manager.locatorAdded( locator );
375
376 }
377
378
379 /**
380 * does not really test anything special, but ensures that the internal
381 * structure is able to parse the addition/ removal
382 */
383 @Test
384 public void LocatorRemoved()
385 {
386
387 DriverLocator locator = Mockito.mock( DriverLocator.class );
388
389 m_manager.locatorAdded( locator );
390 m_manager.locatorRemoved( locator );
391
392 }
393
394
395 /**
396 * does not really test anything special, but ensures that the internal
397 * structure is able to parse the addition
398 * @throws Exception
399 */
400 @Test
401 public void DriverAdded() throws Exception
402 {
403
404 Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", 1 );
405
406 m_manager.driverAdded( m_osgi.getReference( driver ), driver );
407
408 }
409
410
411 /**
412 * does not really test anything special, but ensures that the internal
413 * structure is able to parse the addition/ removal
414 * @throws Exception
415 */
416 @Test
417 public void DriverRemoved() throws Exception
418 {
419
420 Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", 1 );
421
422 ServiceReference ref = m_osgi.getReference( driver );
423
424 m_manager.driverAdded( ref, driver );
425 m_manager.driverRemoved( ref );
426 }
427
428 /**
429 * does not really test anything special, but ensures that the internal
430 * structure is able to parse the addition/ removal
431 * @throws Exception
432 */
433 @Test
434 public void DeviceRemoved() throws Exception
435 {
436
437 Properties p = new Properties();
438 p.put(Constants.DEVICE_CATEGORY, new String[]{"dummy"});
439
440 ServiceReference ref = OSGiMock.createReference(p);
441
442 Object device = new Object();
443
444 m_manager.deviceAdded( ref, device );
445 m_manager.deviceRemoved( ref );
446 }
447
448 /**
449 * does not really test anything special, but ensures that the internal
450 * structure is able to parse the addition/ removal
451 * @throws Exception
452 */
453 @Test
454 public void DeviceModified() throws Exception
455 {
456
457 Properties p = new Properties();
458 p.put(Constants.DEVICE_CATEGORY, new String[]{"dummy"});
459
460 ServiceReference ref = OSGiMock.createReference(p);
461 Object device = new Object();
462
463 m_manager.deviceAdded( ref, new Object() );
464 m_manager.deviceModified(ref, device);
465 }
466 //intended flow, various configurations
467 /**
468 * We add a device, but there are no driver locators, so
469 * the noDriverFound method must be called
470 * @throws InterruptedException
471 */
472 @Test
473 public void DeviceAddedNoDriverLocator() throws InterruptedException
474 {
475
476 //create a mocked device
477 Device device = tstCreateDevice( new String[]
478 { "org.apache.felix" } );
479
480 CountDownLatch latch = tstExpectNoDriverFound( device );
481
482 m_manager.deviceAdded( m_osgi.getReference( device ), device );
483
484 if ( !latch.await( 5, TimeUnit.SECONDS ) )
485 {
486 Assert.fail( "expected call noDriverFound" );
487 }
488
489 }
490
491
492 /**
493 * We add a device, but there are no driver locators, however, there is a driver
494 * that matches. Thus an attach must follow.
495 * @throws Exception
496 */
497 @Test
498 public void DeviceAddedNoDriverLocatorSuccessfulAttach() throws Exception
499 {
500
501 Device device = tstCreateDevice( new String[] { "org.apache.felix" } );
502 Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", 1 );
503
504 CountDownLatch attachLatch = tstExpectAttach( driver, device );
505
506 m_manager.driverAdded( m_osgi.getReference( driver ), driver );
507 m_manager.deviceAdded( m_osgi.getReference( device ), device );
508
509 if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
510 {
511 Assert.fail( "expected attach" );
512 }
513
514 }
515
516
517 /**
518 * We add a device, but there are no driver locators, however, there is a driver
519 * but it sadly doesn't match. Thus a <code>noDriverFound()</code> is called.
520 *
521 * @throws Exception
522 */
523 @Test
524 public void DeviceAddedNoDriverLocatorAttachFails() throws Exception
525 {
526
527 Device device = tstCreateDevice( new String[] { "org.apache.felix" } );
528 Driver driver = tstCreateDriver( "org.apache.felix.driver-1.0", Device.MATCH_NONE );
529
530 CountDownLatch attachLatch = tstExpectNoDriverFound( device );
531
532 m_manager.driverAdded( m_osgi.getReference( driver ), driver );
533 m_manager.deviceAdded( m_osgi.getReference( device ), device );
534
535 if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
536 {
537 Assert.fail( "expected attach" );
538 }
539
540 }
541
542
543 /**
544 * We add a device while there's one driverlocator that will successfully
545 * locate and load two driver bundles. We expect a <code>Driver.attach()</code> for
546 * the best matching driver. There's already a driver loaded that should not match.
547 *
548 * @throws Exception
549 */
550 @Test
551 public void DeviceAddedWithADriverLocator() throws Exception
552 {
553
554 final String driverId1 = "org.apache.felix.driver-1.0";
555 final String driverId2 = "org.apache.felix.driver-1.1";
556 final String notMatchingButLoadedDriverId = "dotorg.apache.felix.driver-1.0";
557
558
559 DriverLocator locator = Mockito.mock( DriverLocator.class );
560
561 Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator,
562 new String[] { driverId1, driverId2 },
563 new int[] { 30, 3 } );
564
565 Driver noMatcher = tstCreateDriver( notMatchingButLoadedDriverId, 100 );
566
567 Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
568
569 final CountDownLatch attachLatch = tstExpectAttach( drivers.get( driverId1 ), device );
570
571 final CountDownLatch unloadDriverLatch = tstExpectUnloadDriverBundle( drivers.get ( driverId2 ) );
572
573 m_manager.locatorAdded( locator );
574
575 m_manager.driverAdded( m_osgi.getReference( noMatcher ), noMatcher );
576
577 m_manager.deviceAdded( m_osgi.getReference( device ), device );
578
579 if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
580 {
581 Assert.fail( "expected an attach" );
582 }
583
584 //since driver1 is attached, we expect an uninstall()
585 //of all other (dynamically loaded) driver bundles
586 if ( !unloadDriverLatch.await( 5, TimeUnit.SECONDS ) )
587 {
588 Assert.fail( "expected an unload" );
589 }
590
591 }
592
593 @Test
594 public void DeviceAddedWithADriverLocatorUnloadFails() throws Exception
595 {
596
597 final String driverId1 = "org.apache.felix.driver-1.0";
598 final String driverId2 = "org.apache.felix.driver-1.1";
599 final String notMatchingButLoadedDriverId = "dotorg.apache.felix.driver-1.0";
600
601
602 DriverLocator locator = Mockito.mock( DriverLocator.class );
603
604 Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator,
605 new String[] { driverId1, driverId2 },
606 new int[] { 30, 3 } );
607
608 Driver noMatcher = tstCreateDriver( notMatchingButLoadedDriverId, 100 );
609
610 Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
611
612 final CountDownLatch attachLatch = tstExpectAttach( drivers.get( driverId1 ), device );
613
614 final CountDownLatch unloadDriverLatch = new CountDownLatch( 1 );
615
616 ServiceReference driver2Ref = m_osgi.getReference( drivers.get( driverId2 ) );
617 Bundle driver2Bundle = m_osgi.getBundle( driver2Ref );
618
619 Answer<Object> answer = new Answer<Object>() {
620
621 public Object answer(InvocationOnMock invocation) throws Throwable {
622 try {
623 throw new BundleException("test driverBundle uninstall failed");
624 }
625 finally {
626 unloadDriverLatch.countDown();
627 }
628 }
629 };
630
631 Mockito.doAnswer(answer).when(driver2Bundle).uninstall();
632
633 m_manager.locatorAdded( locator );
634
635 m_manager.driverAdded( m_osgi.getReference( noMatcher ), noMatcher );
636
637 m_manager.deviceAdded( m_osgi.getReference( device ), device );
638
639 if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
640 {
641 Assert.fail( "expected an attach" );
642 }
643
644 if ( !unloadDriverLatch.await( 5, TimeUnit.SECONDS ) )
645 {
646 Assert.fail( "expected an unload" );
647 }
648
649
650 //since driver1 is attached, we expect an uninstall()
651 //of all other (dynamically loaded) driver bundles
652 //Driver driver = drivers.get( driverId2 );
653 //tstVerifyBundleUninstall( driver );
654 }
655
656 /**
657 * Two drivers equally match the device. There is a driver selector
658 * that comes to the rescue that selects driver2.
659 *
660 * @throws Exception
661 */
662 @Test
663 public void EqualMatchWithDriverSelector() throws Exception
664 {
665
666 final String driverId1 = "org.apache.felix.driver-1.0";
667 final String driverId2 = "org.apache.felix.driver-1.1";
668
669 DriverLocator locator = Mockito.mock( DriverLocator.class );
670
671 Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator,
672 new String[] { driverId1, driverId2 },
673 new int[] { 20, 20 } );
674
675 Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
676
677 DriverSelector selector = Mockito.mock( DriverSelector.class );
678
679 SelectorMatcher matcher = new SelectorMatcher( driverId2 );
680
681 Mockito.when( selector.select(
682 Mockito.eq( m_osgi.getReference( device ) ),
683 Mockito.isA(Match[].class) ) ).thenAnswer( matcher );
684
685 final CountDownLatch attachLatch = tstExpectAttach( drivers.get( driverId2 ), device );
686
687
688 Utils.inject( m_manager, DriverSelector.class, selector );
689
690 m_manager.locatorAdded( locator );
691
692 m_manager.deviceAdded( m_osgi.getReference( device ), device );
693
694 if ( !attachLatch.await( 5, TimeUnit.SECONDS ) )
695 {
696 Assert.fail( "expected an attach" );
697 }
698
699
700 //driver2 is attached, so driver1 bundle should uninstall.
701 //Driver driver = drivers.get( driverId1 );
702 //tstVerifyBundleUninstall( driver );
703
704 }
705
706
707 //exceptional flow
708 @Test
709 public void DriverLocator_findDriverFails() throws Exception
710 {
711
712 final CountDownLatch latch = new CountDownLatch( 1 );
713
714 Answer<String[]> answer = new Answer<String[]>()
715 {
716
717 public String[] answer(InvocationOnMock invocation) throws Throwable
718 {
719 latch.countDown();
720 throw new RuntimeException( "test exception" );
721 }
722 };
723
724 DriverLocator locator = Mockito.mock( DriverLocator.class, "locator" );
725 Mockito.when( locator.findDrivers( Mockito.isA( Dictionary.class ) ) )
726 .thenAnswer( answer );
727
728 Device device = tstCreateDevice( new String[]
729 { "org.apache.felix" } );
730
731 final CountDownLatch latch2 = new CountDownLatch( 1 );
732
733 Answer<Object> answer2 = new Answer<Object>()
734 {
735 public Object answer(InvocationOnMock invocation) throws Throwable
736 {
737 latch2.countDown();
738 return null;
739 }
740 };
741
742 Mockito.doAnswer(answer2).when(device).noDriverFound();
743
744
745 m_manager.locatorAdded( locator );
746 m_manager.deviceAdded( m_osgi.getReference( device ), device );
747
748 if ( !latch.await( 5, TimeUnit.SECONDS ) )
749 {
750 Assert.fail( "expected a call to DriverLocator.findDrivers" );
751 }
752
753 if ( !latch2.await( 5, TimeUnit.SECONDS ) )
754 {
755 Assert.fail( "expected a call to Driver.noDriverFound" );
756 }
757
758 }
759
760
761 /**
762 * This test verified correct behavior when after a driver
763 * attach led to a referral, this referral leads to an exception.
764 *
765 *
766 * @throws Exception
767 */
768 @Ignore
769 public void DriverReferral_ReferralFails() throws Exception
770 {
771
772 final String referredDriver = "org.apache.felix.driver-2.0";
773
774 String[] driverIds = new String[]
775 { "org.apache.felix.driver-1.0", "org.apache.felix.driver-1.1" };
776
777 int[] driverMatches = new int[]{ 1, Device.MATCH_NONE };
778
779 DriverLocator locator = Mockito.mock( DriverLocator.class, "locator for v1.x" );
780 Map<String, Driver> drivers = tstExpectDriverLocatorFor( locator, driverIds, driverMatches );
781
782
783 DriverLocator locatorv2 = Mockito.mock( DriverLocator.class, "locator for v2.x (fails always)" );
784 Mockito.when( locatorv2.findDrivers( Mockito.isA( Dictionary.class ) ) )
785 .thenReturn( null );
786
787 Mockito.when( locatorv2.loadDriver( Mockito.startsWith( "org.apache.felix.driver-1" ) ) )
788 .thenReturn( null );
789
790 InputStream referredInputStream = Mockito.mock(InputStream.class);
791 Mockito.when( locatorv2.loadDriver( referredDriver ) ).thenReturn( referredInputStream );
792
793
794 //this is what initial driver referral eventually leads
795 //to: the loading of a driver bundle
796 //we fake it, so that it fails
797 Mockito.when( m_context.installBundle(
798 Mockito.anyString(),
799 Mockito.isA( InputStream.class ) ) )
800 .thenThrow(new BundleException( "test exception" ) );
801
802 Driver matched = drivers.get( "org.apache.felix.driver-1.0" );
803
804 final CountDownLatch latch = new CountDownLatch( 1 );
805
806 Answer<String> driver10_attach = new Answer<String>()
807 {
808 public String answer(InvocationOnMock invocation) throws Throwable
809 {
810 System.out.println("driver10_attach()");
811 latch.countDown();
812 return referredDriver;
813 }
814 };
815
816 Device device = tstCreateDevice( new String[]{ "org.apache.felix" } );
817
818
819 Mockito.when( matched.match( m_osgi.getReference( device ) ) ).thenReturn( 10 );
820
821 Mockito.when( matched.attach( Mockito.isA( ServiceReference.class ) ) )
822 .thenAnswer( driver10_attach );
823
824// for ( String driverId : driverIds )
825// {
826// Driver driver = drivers.get( driverId );
827// tstExpectBundleUninstall( driver );
828// }
829
830
831 //the actual test
832
833 m_manager.locatorAdded( locator );
834 m_manager.locatorAdded( locatorv2 );
835
836 //depman induced callback
837 m_manager.deviceAdded( m_osgi.getReference( device ), device );
838
839
840 if ( !latch.await( 5, TimeUnit.SECONDS ) )
841 {
842 Assert.fail( "expected an attach to: " + driverIds[0] );
843 }
844
845
846 Mockito.verify(device).noDriverFound();
847 }
848
849 /**
Richard S. Hall3bc8afd2009-08-12 19:03:19 +0000850 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
Stuart McCulloch798b4562009-04-16 09:32:05 +0000851 */
852 private class MatchAnswer implements Answer<Integer>
853 {
854
855 private final ServiceReference m_driverRef;
856
857 public MatchAnswer( ServiceReference driverRef )
858 {
859 m_driverRef = driverRef;
860 }
861
862
863 public Integer answer(InvocationOnMock invocation) throws Throwable
864 {
865 ServiceReference deviceRef = ( ServiceReference ) invocation.getArguments()[0];
866 String[] categories = String[].class.cast( deviceRef.getProperty( Constants.DEVICE_CATEGORY ) );
867 String driverId = String.class.cast( m_driverRef.getProperty( Constants.DRIVER_ID ) );
868
869 for ( String string : categories )
870 {
871 if ( driverId.startsWith( string ) )
872 {
873 Object match = m_driverRef.getProperty( "match" );
874 return Integer.valueOf( match.toString() );
875 }
876 }
877 return Device.MATCH_NONE;
878 }
879
880 }
881
882
883 private class SelectorMatcher implements Answer<Integer>
884 {
885
886 private String m_driverId;
887
888
889 public SelectorMatcher( String driverId )
890 {
891 m_driverId = driverId;
892 }
893
894 public Integer answer(InvocationOnMock invocation) throws Throwable
895 {
896 int i = 0;
897 Match[] matches = (Match[])invocation.getArguments()[1];
898
899 for ( Match match : matches )
900 {
901 if ( match.getDriver().getProperty( Constants.DRIVER_ID ).equals( m_driverId ) )
902 {
903 return i;
904 }
905 i++;
906 }
907 return DriverSelector.SELECT_NONE;
908 }
909
910
911 }
912
913}