    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    }