001    /*****************************************************************************
002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *                                                                           *
008     * Original code by Joerg Schaible                                           *
009     *****************************************************************************/
010    package org.picocontainer.injectors;
011    
012    import org.picocontainer.injectors.AbstractInjector;
013    
014    import junit.framework.TestCase;
015    
016    /**
017     * Test the CyclicDependecy.
018     */
019    public final class ThreadLocalCyclicDependencyGuardTestCase
020            extends TestCase {
021        private final Runnable[] runner = new Runnable[3];
022        
023        class ThreadLocalRunner implements Runnable {
024            public AbstractInjector.CyclicDependencyException exception;
025            private final Blocker blocker;
026            private final AbstractInjector.ThreadLocalCyclicDependencyGuard guard;
027    
028            public ThreadLocalRunner() {
029                this.blocker = new Blocker();
030                this.guard = new AbstractInjector.ThreadLocalCyclicDependencyGuard() {
031                    public Object run() {
032                        try {
033                            blocker.block();
034                        } catch (InterruptedException e) {
035                        }
036                        return null;
037                    }
038                };
039            }
040    
041            public void run() {
042                try {
043                    guard.observe(ThreadLocalRunner.class);
044                } catch (AbstractInjector.CyclicDependencyException e) {
045                    exception = e;
046                }
047            }
048        }
049    
050        public class Blocker {
051            public void block() throws InterruptedException {
052                final Thread thread = Thread.currentThread();
053                synchronized (thread) {
054                    thread.wait();
055                }
056            }
057        }
058    
059        private void initTest(final Runnable[] runner) throws InterruptedException {
060    
061            Thread racer[] = new Thread[runner.length];
062            for(int i = 0; i < racer.length; ++i) {
063                racer[i] =  new Thread(runner[i]);
064            }
065    
066            for (Thread aRacer : racer) {
067                aRacer.start();
068                Thread.sleep(200);
069            }
070    
071            for (Thread aRacer : racer) {
072                synchronized (aRacer) {
073                    aRacer.notify();
074                }
075            }
076    
077            for (Thread aRacer : racer) {
078                aRacer.join();
079            }
080        }
081        
082        public void testCyclicDependencyWithThreadSafeGuard() throws InterruptedException {
083            for(int i = 0; i < runner.length; ++i) {
084                runner[i] = new ThreadLocalRunner();
085            }
086            
087            initTest(runner);
088    
089            for (Runnable aRunner : runner) {
090                assertNull(((ThreadLocalRunner) aRunner).exception);
091            }
092        }
093    
094        public void testCyclicDependencyException() {
095            final AbstractInjector.CyclicDependencyException cdEx = new AbstractInjector.CyclicDependencyException(getClass());
096            cdEx.push(String.class);
097            final Class[] classes = cdEx.getDependencies();
098            assertEquals(2, classes.length);
099            assertSame(getClass(), classes[0]);
100            assertSame(String.class, classes[1]);
101            assertTrue(cdEx.getMessage().indexOf(getClass().getName()) >= 0);
102        }
103    
104    
105    
106    }