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 static org.junit.Assert.assertEquals;
013    import static org.junit.Assert.assertNull;
014    import static org.junit.Assert.assertSame;
015    import static org.junit.Assert.assertTrue;
016    
017    import org.junit.Test;
018    
019    /**
020     * Test the CyclicDependecy.
021     */
022    public final class ThreadLocalCyclicDependencyGuardTestCase {
023          
024        private final Runnable[] runner = new Runnable[3];
025        
026        class ThreadLocalRunner implements Runnable {
027            public AbstractInjector.CyclicDependencyException exception;
028            private final Blocker blocker;
029            private final AbstractInjector.ThreadLocalCyclicDependencyGuard guard;
030    
031            public ThreadLocalRunner() {
032                this.blocker = new Blocker();
033                this.guard = new AbstractInjector.ThreadLocalCyclicDependencyGuard() {
034                    public Object run() {
035                        try {
036                            blocker.block();
037                        } catch (InterruptedException e) {
038                        }
039                        return null;
040                    }
041                };
042            }
043    
044            public void run() {
045                try {
046                    guard.observe(ThreadLocalRunner.class);
047                } catch (AbstractInjector.CyclicDependencyException e) {
048                    exception = e;
049                }
050            }
051        }
052    
053        public class Blocker {
054            public void block() throws InterruptedException {
055                final Thread thread = Thread.currentThread();
056                synchronized (thread) {
057                    thread.wait();
058                }
059            }
060        }
061    
062        private void initTest(final Runnable[] runner) throws InterruptedException {
063    
064            Thread racer[] = new Thread[runner.length];
065            for(int i = 0; i < racer.length; ++i) {
066                racer[i] =  new Thread(runner[i]);
067            }
068    
069            for (Thread aRacer : racer) {
070                aRacer.start();
071                Thread.sleep(200);
072            }
073    
074            for (Thread aRacer : racer) {
075                synchronized (aRacer) {
076                    aRacer.notify();
077                }
078            }
079    
080            for (Thread aRacer : racer) {
081                aRacer.join();
082            }
083        }
084        
085        @Test public void testCyclicDependencyWithThreadSafeGuard() throws InterruptedException {
086            for(int i = 0; i < runner.length; ++i) {
087                runner[i] = new ThreadLocalRunner();
088            }
089            
090            initTest(runner);
091    
092            for (Runnable aRunner : runner) {
093                assertNull(((ThreadLocalRunner) aRunner).exception);
094            }
095        }
096    
097        @Test public void testCyclicDependencyException() {
098            final AbstractInjector.CyclicDependencyException cdEx = new AbstractInjector.CyclicDependencyException(getClass());
099            cdEx.push(String.class);
100            final Class[] classes = cdEx.getDependencies();
101            assertEquals(2, classes.length);
102            assertSame(getClass(), classes[0]);
103            assertSame(String.class, classes[1]);
104            assertTrue(cdEx.getMessage().indexOf(getClass().getName()) >= 0);
105        }
106    
107    
108    
109    }