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.defaults;
011    
012    import junit.framework.TestCase;
013    
014    /**
015     * Test the CyclicDependecy.
016     */
017    public class CyclicDependencyGuardTestCase
018            extends TestCase {
019        private Runnable[] runner = new Runnable[3];
020        
021        class ThreadLocalRunner implements Runnable {
022            public CyclicDependencyException exception;
023            private final Blocker blocker;
024            private final CyclicDependencyGuard guard;
025    
026            public ThreadLocalRunner() {
027                this.blocker = new Blocker();
028                this.guard = new ThreadLocalCyclicDependencyGuard() {
029                    public Object run() {
030                        try {
031                            blocker.block();
032                        } catch (InterruptedException e) {
033                        }
034                        return null;
035                    }
036                };
037            }
038    
039            public void run() {
040                try {
041                    guard.observe(ThreadLocalRunner.class);
042                } catch (CyclicDependencyException e) {
043                    exception = e;
044                }
045            }
046        }
047    
048        public class Blocker {
049            public void block() throws InterruptedException {
050                final Thread thread = Thread.currentThread();
051                synchronized (thread) {
052                    thread.wait();
053                }
054            }
055        }
056    
057        private void initTest(final Runnable[] runner) throws InterruptedException {
058    
059            Thread racer[] = new Thread[runner.length];
060            for(int i = 0; i < racer.length; ++i) {
061                racer[i] =  new Thread(runner[i]);
062            }
063    
064            for(int i = 0; i < racer.length; ++i) {
065                racer[i].start();
066                Thread.sleep(200);
067            }
068            
069            for(int i = 0; i < racer.length; ++i) {
070                synchronized (racer[i]) {
071                    racer[i].notify();
072                }
073            }
074    
075            for(int i = 0; i < racer.length; ++i) {
076                racer[i].join();
077            }
078        }
079        
080        public void testCyclicDependencyWithThreadSafeGuard() throws InterruptedException {
081            for(int i = 0; i < runner.length; ++i) {
082                runner[i] = new ThreadLocalRunner();
083            }
084            
085            initTest(runner);
086    
087            for(int i = 0; i < runner.length; ++i) {
088                assertNull(((ThreadLocalRunner)runner[i]).exception);
089            }
090        }
091    }