    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                                                          *
    009     *****************************************************************************/
    010    package org.picocontainer.defaults.issues;
    011
    012    import static org.junit.Assert.assertTrue;
    013
    014    import java.util.ArrayList;
    015    import java.util.List;
    016
    017    import org.junit.Test;
    018    import org.picocontainer.DefaultPicoContainer;
    019    import org.picocontainer.PicoContainer;
    020    import org.picocontainer.behaviors.Synchronizing;
    021    import org.picocontainer.injectors.ConstructorInjection;
    022
    023    public final class Issue0199TestCase {
    024
    025        public static class A {
    026            public A(C c) {}
    027        }
    028
    029        public static class B {
    030            public B(C c) {}
    031        }
    032
    033        public static class C {}
    034
    035        final class Runner extends Thread {
    036            private final PicoContainer container;
    037            private final Object componentKey;
    038            private Throwable throwable;
    039            private boolean finished;
    040
    041            Runner(String name, PicoContainer container, Object componentKey) {
    042                super(name);
    043                this.container = container;
    044                this.componentKey = componentKey;
    045            }
    046
    047            public void run() {
    048                try {
    049                    report("Started instantiating " + componentKey.toString());
    050                    container.getComponent(componentKey);
    051                    report("Finished instantiating " + componentKey.toString());
    052                    finished = true;
    053                } catch (Throwable t) {
    054                    this.throwable = t;
    055                }
    056            }
    057
    058            private void report(String messsage) {
    059                System.out.println(getName() + ": " + messsage);
    060            }
    061
    062            public boolean isFinished() {
    063                return finished;
    064            }
    065
    066            public Throwable getThrowable() {
    067                return throwable;
    068            }
    069        }
    070
    071        @Test public void testPicoContainerCausesDeadlock() throws InterruptedException {
    072            DefaultPicoContainer container = createContainer();
    073            container.addComponent("A", A.class);
    074            container.addComponent("B", B.class);
    075            container.addComponent("C", C.class);
    076
    077            final int THREAD_COUNT = 2;
    078            List runnerList = new ArrayList(THREAD_COUNT);
    079
    080            for (int i = 0; i < THREAD_COUNT; ++i) {
    081                Runner runner = new Runner("Runner " + i, container, (i % 2 == 0) ? "A" : "B");
    082                runnerList.add(runner);
    083                runner.start();
    084            }
    085
    086            final long WAIT_TIME = 1000;
    087
    088            for (int i = 0; i < THREAD_COUNT; ++i) {
    089                Runner runner = (Runner) runnerList.get(i);
    090                runner.join(WAIT_TIME);
    091                assertTrue("Deadlock occurred", runner.isFinished());
    092            }
    093        }
    094
    095        private DefaultPicoContainer createContainer() {
    096            return new DefaultPicoContainer(
    097                    new Synchronizing().wrap(new ConstructorInjection()));
    098        }
    099    }