Package tests.jfun.yan.tck

Source Code of tests.jfun.yan.tck.BaseContainerTestCase

/*****************************************************************************
* Copyright (C) PicoContainer Organization. All rights reserved.            *
* ------------------------------------------------------------------------- *
* The software in this package is published under the terms of the BSD      *
* style license a copy of which has been included with this distribution in *
* the LICENSE.txt file.                                                     *
*                                                                           *
* Original code by                                                          *
*****************************************************************************/
package tests.jfun.yan.tck;
import jfun.yan.*;
import junit.framework.Assert;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import tests.jfun.models.Automobile;
import tests.jfun.models.CopyCommand;
import tests.jfun.models.Echo;
import tests.jfun.models.MyBean;
import tests.jfun.models.Struct;
//import tests.jfun.yan.InstanceCounter;
import tests.jfun.yan.testmodel.CarEngine;
import tests.jfun.yan.testmodel.DependsOnTouchable;

import tests.jfun.yan.testmodel.Mtds;

import tests.jfun.yan.testmodel.SimpleTouchable;
import tests.jfun.yan.testmodel.StatefulResource;
import tests.jfun.yan.testmodel.Touchable;
import tests.jfun.yan.testmodel.Washable;
import tests.jfun.yan.testmodel.WashableTouchable;


import java.beans.IntrospectionException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;



import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Creator;
import jfun.yan.IrresolveableArgumentException;
import jfun.yan.UnresolvedComponentException;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
import jfun.yan.containers.DelegatingContainer;
import jfun.yan.containers.SimpleContainer;
import jfun.yan.etc.Beans;
import jfun.yan.factory.ThreadLocalScope;
import jfun.yan.function.Function;

import jfun.yan.lifecycle.ExceptionHandlers;

import jfun.yan.lifecycle.Lifecycle;
import jfun.yan.lifecycle.Phase;
import jfun.yan.lifecycle.DefaultLifecycleDescriptor;
import jfun.yan.lifecycle.DefaultLifecycleManager;

/**
* This test tests (at least it should) all the methods in MutablePicoContainer.
*/
public class BaseContainerTestCase extends TestCase implements java.io.Serializable {
  public static void main(String[] args){
    tests.jfun.yan.Utils.runTest(suite());
  }
  private static TestSuite suite(){
    return new TestSuite(BaseContainerTestCase.class);
  }
    protected final DefaultContainer
    createPicoContainerWithDependsOnTouchableOnly(){
      DefaultContainer yan = new DefaultContainer();
      yan.registerConstructor(DependsOnTouchable.class);
      return yan;

    }

    protected final DefaultContainer createPicoContainerWithTouchableAndDependsOnTouchable() {
        DefaultContainer yan = createPicoContainerWithDependsOnTouchableOnly();
        yan.registerConstructor(Touchable.class, SimpleTouchable.class);
        return yan;
    }

    public void testUpDownDependenciesCannotBeFollowed()
    throws Exception{
        Container parent = createYanContainer();
        Container child = createYanContainer().inherit(parent);
        //child = trans(child);
        // ComponentF -> ComponentA -> ComponentB+c
        child.registerConstructor(ComponentF.class);
        parent.registerConstructor(ComponentA.class);
        parent.registerConstructor(ComponentB.class);
        child.registerConstructor(ComponentC.class);
        try{
          child.getInstance(ComponentF.class);
          fail("should not resolve C");
        }
        catch(IrresolveableArgumentException e){
          //e.printResolutionTrace();
          assertEquals(3, e.getResolutionTrace().size());
          assertEntry(e, 0, "parameter 1 of <public tests.jfun.yan.tck.BaseContainerTestCase$ComponentA(tests.jfun.yan.tck.BaseContainerTestCase$ComponentB,tests.jfun.yan.tck.BaseContainerTestCase$ComponentC)>");
          assertEntry(e, 1, "parameter 0 of <public tests.jfun.yan.tck.BaseContainerTestCase$ComponentF(tests.jfun.yan.tck.BaseContainerTestCase$ComponentA)>");
          assertEntry(e, 2, "getInstance <class tests.jfun.yan.tck.BaseContainerTestCase$ComponentF>");
          assertParameter(e, 0, ComponentA.class, 1);
          assertParameter(e, 1, ComponentF.class, 0);
          assertEquals(ComponentC.class, e.getParameterType());
        }
       
//      ComponentF1 -> ComponentA1 -> ComponentB1+C1 -> ComponentD
        child.registerConstructor(ComponentF1.class);
        parent.registerConstructor(ComponentA1.class);
        parent.registerConstructor(ComponentB1.class);
        parent.registerConstructor(ComponentC1.class);
        child.registerConstructor(ComponentD.class);
        try{
          child.getInstance(ComponentF1.class);
          fail("should not resolve D");
        }
        catch(IrresolveableArgumentException e){
          //e.printResolutionTrace(System.err);
          assertEquals(4, e.getResolutionTrace().size());
          assertEntry(e, 3, "getInstance <class tests.jfun.yan.tck.BaseContainerTestCase$ComponentF1>");
          assertParameter(e, 0, ComponentC1.class, 0);
          assertParameter(e, 1, ComponentA1.class, 1);
          assertParameter(e, 2, ComponentF1.class, 0);
          assertEquals(ComponentD.class, e.getParameterType());
        }
       

    }

    public void testRegisteredComponentsExistAndAreTheCorrectTypes()
    throws Exception{
        Container yan = createPicoContainerWithTouchableAndDependsOnTouchable();
        yan = trans(yan);
        yan.verify();
        assertNotNull("Container should have Touchable component",
                yan.getInstance(Touchable.class));
        assertNotNull("Container should have DependsOnTouchable component",
                yan.getInstance(DependsOnTouchable.class));
        assertTrue("Component should be instance of Touchable",
                yan.getInstance(Touchable.class) instanceof Touchable);
        assertTrue("Component should be instance of DependsOnTouchable",
                yan.getInstance(DependsOnTouchable.class) instanceof DependsOnTouchable);
        assertNull("should not have non existent component", yan.getComponent(Map.class));
    }

    public void testRegistersSingleInstance(){
        DefaultContainer yan = new DefaultContainer();
        StringBuffer sb = new StringBuffer();
        yan.registerValue(sb);
        yan.verify();
        assertSame(sb, yan.getInstance(StringBuffer.class));
    }
    public void testGettingComponentWithMissingDependencyFails(){
        SimpleContainer picoContainer = createPicoContainerWithDependsOnTouchableOnly();
        try {
            picoContainer.getInstance(DependsOnTouchable.class);
            fail("should need a Touchable");
        } catch (jfun.yan.YanException e) {
          assertEquals(2, e.getResolutionTrace().size());
          assertParameter(e, 0, DependsOnTouchable.class, 0);
        }
    }
    public void testVerifyWithMissingDependencyFails(){
      SimpleContainer picoContainer = createPicoContainerWithDependsOnTouchableOnly();
      try {
          picoContainer.verify();
          fail("should need a Touchable");
      } catch (jfun.yan.YanException e) {
      }
  }
    public void testExternallyInstantiatedObjectsCanBeRegistgeredAndLookedUp(){
        DefaultContainer yan = new DefaultContainer();
        final HashMap map = new HashMap();
        yan.registerValue(Map.class, map);
        yan.verify();
        assertSame(map, yan.getInstance(Map.class));
    }


    public void testLookupWithUnregisteredKeyReturnsNull(){
        DefaultContainer yan = new DefaultContainer();
        assertNull(yan.getComponent(String.class));
    }

    public static class ListAdder {
        public ListAdder(Collection list) {
            list.add("something");
        }
    }


    public void testCyclicDependencyThrowsCyclicDependencyException()
    throws Exception{
        Container yan = new DefaultContainer();
        yan.registerConstructor(ComponentB.class);
        yan.registerConstructor(ComponentD.class);
        yan.registerConstructor(ComponentE.class);
        yan = trans(yan);

        try {
            yan.getInstance(ComponentD.class);
            fail("CyclicDependencyException expected");
        } catch (jfun.yan.CyclicDependencyException e) {
            // CyclicDependencyException reports now the stack.
            //final List dependencies = Arrays.asList(ComponentD.class.getConstructors()[0].getParameterTypes());
            //final List dependencies = Arrays.asList(new Class[]{ComponentD.class, ComponentE.class, ComponentD.class});
            //final List reportedDependencies = Arrays.asList(e.getDependencies());
            //assertEquals(dependencies, reportedDependencies);
          //e.printResolutionTrace(System.err);
          assertEquals(3, e.getResolutionTrace().size());
          assertEntry(e, 2, "getInstance <class tests.jfun.yan.tck.BaseContainerTestCase$ComponentD>");
          assertParameter(e, 0, ComponentE.class, 0);
          assertParameter(e, 1, ComponentD.class, 0);
          //e.printResolutionTrace(System.err);
        } catch (StackOverflowError e) {
            fail();
        }
    }
    protected void assertParameter(YanException e, int i, Class c, int k){
      assertParameter(e, i, Functions.ctor(c), k);
    }
    protected void assertParameter(YanException e, int i, Function f, int k){
      final Stack trace = e.getResolutionTrace();
      assertEquals(new ParameterEntry(f, k), trace.get(i));
    }
    protected void assertTraceSize(YanException e, int s){
      assertEquals(s, e.getResolutionTrace().size());
    }
    protected void assertEntry(YanException e, int i, String txt){
      assertEquals(txt, ""+e.getResolutionTrace().get(i));
    }
    public void assertEntry(YanException e, int i, Object obj){
      assertEquals(obj, e.getResolutionTrace().get(i));
    }
    private void assertProperty(YanException e, int i, Class c, Object k){
      final Stack trace = e.getResolutionTrace();
      assertEquals(new PropertyEntry(c, k), trace.get(i));
    }
    public void testVerifyCyclicDependencyThrowsCyclicDependencyException() {
      DefaultContainer yan = new DefaultContainer();
      yan.registerConstructor(ComponentB.class);
      yan.registerConstructor(ComponentD.class);
      yan.registerConstructor(ComponentE.class);

      try {
          yan.verify();
          fail("CyclicDependencyException expected");
      } catch (jfun.yan.CyclicDependencyException e) {
        assertEquals(3, e.getResolutionTrace().size());
        assertParameter(e, 0, ComponentE.class, 0);
        assertParameter(e, 1, ComponentD.class, 0);
        assertEntry(e, 2, "verify <class tests.jfun.yan.tck.BaseContainerTestCase$ComponentD>");
      } catch (StackOverflowError e) {
          fail();
      }
  }
    public void testRemovalNonRegisteredComponentAdapterWorksAndReturnsNull() {
        final DefaultContainer picoContainer = new DefaultContainer();
        picoContainer.unregisterComponent("COMPONENT DOES NOT EXIST");
    }
    public static class NeedsTouchable {
        public Touchable touchable;

        public NeedsTouchable(Touchable touchable) {
            this.touchable = touchable;
        }
    }

    public static class NeedsWashable {
        public Washable washable;

        public NeedsWashable(Washable washable) {
            this.washable = washable;
        }
    }

    public void testSameInstanceCanBeUsedAsDifferentType() {
        DefaultContainer yan = new DefaultContainer();
        yan.registerConstructor("wt", WashableTouchable.class);
        yan.registerConstructor("nw", NeedsWashable.class);
        yan.registerConstructor("nt", NeedsTouchable.class);

        NeedsWashable nw = (NeedsWashable) yan.getInstance("nw");
        NeedsTouchable nt = (NeedsTouchable) yan.getInstance("nt");
        assertSame(nw.washable, nt.touchable);
    }


    public static class JMSService {
        public final String serverid;
        public final String path;

        public JMSService(String serverid, String path) {
            this.serverid = serverid;
            this.path = path;
        }
    }

    // http://jira.codehaus.org/secure/ViewIssue.jspa?key=PICO-52
    public void testPico52() {
        DefaultContainer yan = new DefaultContainer();

        yan.registerComponent("foo",
            Components.singleton(
                Components.withArguments(
                Components.ctor(JMSService.class),
                new jfun.yan.Creator[]{
                    Components.value("0"),
                    Components.value("something")
                })
            )
        );
        JMSService jms = (JMSService) yan.getInstance("foo");
        assertEquals("0", jms.serverid);
        assertEquals("something", jms.path);
    }

    public static class ComponentA {
        public ComponentA(ComponentB b, ComponentC c) {
            Assert.assertNotNull(b);
            Assert.assertNotNull(c);
        }
    }

    public static class ComponentA1 {
      public ComponentA1(ComponentB1 b, ComponentC1 c) {
          Assert.assertNotNull(b);
          Assert.assertNotNull(c);
      }
  }
    public static class ComponentB1 {
    }

    public static class ComponentC1 {
      public ComponentC1(ComponentD d){
        Assert.assertNotNull(d);
      }
    }


    public static class ComponentB {
    }

    public static class ComponentC {
    }

    public static class ComponentD {
        public ComponentD(ComponentE e, ComponentB b) {
            Assert.assertNotNull(e);
            Assert.assertNotNull(b);
        }
    }

    public static class ComponentE {
        public ComponentE(ComponentD d) {
            Assert.assertNotNull(d);
        }
    }

    public static class ComponentF {
        public ComponentF(ComponentA a) {
            Assert.assertNotNull(a);
        }
    }

    public static class ComponentF1 {
      public ComponentF1(ComponentA1 a) {
          Assert.assertNotNull(a);
      }
  }

    public static class ContainerDependency {
        public ContainerDependency(SimpleContainer container) {
            assertNotNull(container);
        }
    }

    // ImplicitPicoContainer injection is bad. It is an open door for hackers. Developers with
    // special SimpleContainer needs should specifically register() a comtainer they want components to
    // be able to pick up on.

//    public void testImplicitPicoContainerInjection() {
//        DefaultContainer yan = new DefaultContainer();
//        yan.registerConstructor(ContainerDependency.class);
//        ContainerDependency dep = (ContainerDependency) yan.getInstance(ContainerDependency.class);
//        assertSame(yan, dep.yan);
//    }



    static class Foo implements java.io.Serializable{
        public boolean started;
        public boolean stopped;
        public boolean disposed;

        public void start() {
            started = true;
        }

        public void stop() {
            stopped = true;
        }

        public void dispose() {
            disposed = true;
        }

    }
    /*
    private static class MemberCallback implements jfun.yan.InstanceListener{
      private final Class type;
      private final Method mtd;
      private final Object[] args;
     
      MemberCallback(final Class type, final Method mtd, final Object[] args) {
        this.type = type;
        this.mtd = mtd;
        this.args = args;
      }
      MemberCallback(final Class type, final Method mtd) {
        this.type = type;
        this.mtd = mtd;
        this.args = new Object[0];
      }
      MemberCallback(final Class type, String name) {
        try{
          this.type = type;
          this.mtd = type.getMethod(name, new Class[0]);
          this.args = new Object[0];
        }
        catch(RuntimeException e){throw e;}
        catch(Exception e){
          throw new IllegalStateException(e.getMessage());
        }
      }
      public void onInstance(Object obj, Component cc){
        if(type.isInstance(obj)){
          try{
            mtd.invoke(obj, args);
          }
          catch(RuntimeException e){throw e;}
          catch(Exception e){
            throw new IllegalStateException(e.getMessage());
          }
        }
      }
    }
    public void testContainerCascadesStart() {
        final DefaultContainer container = new DefaultContainer();
        Foo foo = new Foo();
        container.registerValue(foo);
        container.getInstances();
        container.verify();
        container.fifo(new MemberCallback(Foo.class, "start"));
        assertEquals(true, foo.started);
    }

    public void testContainerCascadesStop()
    throws Exception{
        Container picoContainer = new DefaultContainer();
        Foo foo = new Foo();
        picoContainer.registerValue(foo);
        picoContainer.getInstances();
        picoContainer.fifo(new MemberCallback(Foo.class, "start"));
        picoContainer.filo(new MemberCallback(Foo.class, "stop"));
        picoContainer = trans(picoContainer);
        assertEquals(true, foo.stopped);
    }
   
    public void testContainerCascadesDispose() {
        final DefaultContainer picoContainer = new DefaultContainer();
        Foo foo = new Foo();
        picoContainer.registerValue(foo);
        picoContainer.getInstances();
        picoContainer.filo(new MemberCallback(Foo.class, "dispose"));
        assertEquals(true, foo.disposed);
    }
*/
    public void testComponentInstancesFromParentsAreDirectlyAccessible2() {
        final Container a = new DefaultContainer();
        final Container b = new DefaultContainer().inherit(a);
        final Container c = new DefaultContainer().inherit(b);

        Object ao = new Object();
        Object bo = new Object();
        Object co = new Object();

        a.registerValue("a", ao);
        b.registerValue("b", bo);
        c.registerValue("c", co);

        assertEquals(1, a.getInstances().size());
        assertEquals(2, b.getInstances().size());
        assertEquals(3, c.getInstances().size());
    }
//parent should not cascade to children.
    /*
    public void testStartStopAndDisposeCascadedtoChildren() {
        final DefaultContainer parent = new DefaultContainer();
        parent.registerValue(new StringBuffer());
        StringBuffer sb = (StringBuffer) ((Component) parent
            .getComponentsOfType(StringBuffer.class).get(0))
            .create(parent.getDependencyOfType(StringBuffer.class, parent));
        final CCContainer child = new DefaultContainer().inherit(parent);
        //parent.addChildContainer(child);
        child.registerConstructor(LifeCycleMonitoring.class);
        parent.start();
        assertTrue(sb.toString().indexOf("-started") != -1);
        parent.stop();
        assertTrue(sb.toString().indexOf("-stopped") != -1);
        parent.dispose();
        assertTrue(sb.toString().indexOf("-disposed") != -1);

    }

    public void testStartStopAndDisposeNotCascadedtoRemovedChildren() {
        final DefaultContainer parent = new DefaultContainer();
        parent.registerValue(new StringBuffer());
        StringBuffer sb = (StringBuffer) parent.getComponentInstancesOfType(StringBuffer.class).get(0);

        final DefaultContainer child = createPicoContainer(parent);
        assertTrue(parent.addChildContainer(child));
        child.registerConstructor(LifeCycleMonitoring.class);
        assertTrue(parent.removeChildContainer(child));
        parent.start();
        assertTrue(sb.toString().indexOf("-started") == -1);
        parent.stop();
        assertTrue(sb.toString().indexOf("-stopped") == -1);
        parent.dispose();
        assertTrue(sb.toString().indexOf("-disposed") == -1);
    }
    public void testShouldCascadeStartStopAndDisposeToChild() {
        StringBuffer sb = new StringBuffer();
        final DefaultContainer parent = new DefaultContainer();
        parent.registerValue(sb);
        parent.registerConstructor(Map.class, HashMap.class);

        final SimpleContainer child = parent.inherit(new DefaultContainer());
        child.registerConstructor(LifeCycleMonitoring.class);

        Map map = (Map) parent.getInstance(Map.class);
        assertNotNull(map);
        assertTrue(sb.toString().indexOf("-started") == -1);

        parent.start();
        assertTrue(sb.toString().indexOf("-started") != -1);
        parent.stop();
        assertTrue(sb.toString().indexOf("-stopped") != -1);
        parent.dispose();
        assertTrue(sb.toString().indexOf("-disposed") != -1);
    }

    */



    public void testAmbiguousDependencies(){

        DefaultContainer yan = new DefaultContainer();

        // Register two Touchables that Fred will be confused about
        yan.registerConstructor(SimpleTouchable.class);
        yan.registerConstructor(DerivedTouchable.class);

        // Register a confused DependsOnTouchable
        yan.registerConstructor(DependsOnTouchable.class);
        assertEquals(DependsOnTouchable.class, yan.getComponentType(DependsOnTouchable.class));
        assertNull(yan.getComponentType(Touchable.class));
        try {
            yan.getInstance(DependsOnTouchable.class);
            fail("DependsOnTouchable should have been confused about the two Touchables");
        } catch (jfun.yan.AmbiguousComponentResolutionException e) {
          assertEquals(2, e.getResolutionTrace().size());
          assertParameter(e, 0, DependsOnTouchable.class, 0);
          assertEquals(Touchable.class, e.getComponentKey());
          if(DerivedTouchable.class.equals(e.getType1())){
            assertEquals(SimpleTouchable.class, e.getType2());
          }
          else if(SimpleTouchable.class.equals(e.getType1())){
            assertEquals(DerivedTouchable.class, e.getType2());
          }
          else fail();
         
        }
    }

    public static class DerivedTouchable extends SimpleTouchable {
        public DerivedTouchable() {
        }
    }
    protected final Container createYanContainer(){
      final Container yan = getContainerImpl();
      return new DelegatingContainer(yan){
        public void registerComponent(Object key, Component cc){
          test(cc);
          super.registerComponent(key, cc);
        }
        public void registerComponent(Component cc){
          test(cc);
          super.registerComponent(cc);
        }
        private void test(Component cc){
          assertEquals(cc, cc);
          if(cc!=null)
            assertFalse(cc.equals(null));
          final HashMap hmap = new HashMap();
          hmap.put(cc, cc);
          final Component cc1 = (Component)hmap.get(cc);
          assertEquals(cc, cc1);
          assertEquals(""+cc, ""+cc1);
        }
      };
    }
    protected Container getContainerImpl(){
      return new DefaultContainer();
    }
    public void testSize(){
      final Container yan = createYanContainer();
      String s1 = "hello world";
      yan.registerValue(s1);
      yan.registerValue(s1);
      yan.registerComponent(String.class, Components.value(s1).singleton());
      yan.registerConstructor(java.util.ArrayList.class, (Class[])null);
      assertEquals(2, yan.keys().size());
      assertEquals(2, yan.getInstances().size());
    }
    /*
    protected void assertSize(int s, jfun.yan.Container yan){
      assertEquals(s, InstanceCounter.countInstance(yan));
    }
   
    public void testClearHistory(){
      final Container yan = createYanContainer();
      final java.util.HashMap props = new java.util.HashMap();
      props.put("name", "tom");
      yan.registerComponent(String.class, Components.value("hello")
          .withProperties(props));
      yan.registerConstructor(java.util.ArrayList.class, (Class[])null);
      assertSize(0, yan);
      assertEquals("hello", yan.getInstance(String.class));
      assertEquals("hello", yan.getInstanceOfType(CharSequence.class));
      assertSize(1, yan);
      assertTrue(yan.getInstance(java.util.ArrayList.class) instanceof java.util.ArrayList);
      assertSize(2, yan);
      assertEquals(2, yan.getInstancesOfType(Object.class).size());
      assertEquals(0, ((java.util.ArrayList)yan.getInstanceOfType(java.util.List.class)).size());
      yan.clearHistory();
      assertSize(0, yan);
    }*/
    public void testSubsume(){
      final Container yan = createYanContainer();
      yan.registerComponent(Components.ctor(String.class, null).subsume(CharSequence.class));
      final Object str1 = yan.getInstance(CharSequence.class);
      final Object str2 = yan.getInstanceOfType(CharSequence.class);
      assertEquals(str1, "");
      assertEquals(str2, "");
      if(str1!=str2){
        try{
          yan.getInstanceOfType(String.class);
          fail("should have failed");
        }
        catch(UnresolvedComponentException e){
          assertEquals(1, e.getResolutionTrace().size());
          assertEntry(e, 0, "getInstanceOfType <java.lang.String>");
          assertEquals(String.class, e.getComponentKey());
        }
      }
    }
    public void testArray(){
      final Container yan = createYanContainer();
      yan.registerComponent(int[].class,
          Components.static_method(java.lang.reflect.Array.class,
              "newInstance", new Class[]{Class.class, int.class})
          .cast(int[].class)
          .withArgument(0, Components.useKey("array_dimension")));
      yan.registerValue(new Integer(5));
      yan.registerValue("array_dimension", int.class);
      assertTrue(yan.getInstance(int[].class) instanceof int[]);
      assertEquals(5, ((int[])yan.getInstanceOfType(int[].class)).length);
    }
    public static Object returnNull(){return null;}
    public Object id(Object obj){return obj;}
    public int id(int i){return i;}
    private void testNullInstance(Container yan){
      yan.registerComponent("target", Components.method(this,
          "id", new Class[]{Object.class}));
     yan.verify();
     assertSame(null, yan.getInstance("target"));
     assertEquals(2, yan.getInstancesOfType(Object.class).size());
     assertSame(null, yan.getInstancesOfType(Object.class).get(0));
     assertSame(null, yan.getInstancesOfType(Object.class).get(1));
     //assertSize(0, yan);
     yan.verify();
    
     yan.registerComponent("target", Components.method(this,
         "id", new Class[]{Object.class})
         .withArgument(0, Components.value(null)));
     assertSame(null, yan.getInstance("target"));
     yan.registerComponent("target", Components.method(this,
         "id", new Class[]{int.class})
         .withArgument(0, Components.value(null))
         .singleton().singleton()
         .singleton(new ThreadLocalScope()));
    
     try{
       yan.verify();
       fail("should have failed");
     }
     catch(ParameterTypeMismatchException e){
       assertEquals(2, e.getResolutionTrace().size());
       assertParameter(e, 0,
           Functions.method(this, "id", new Class[]{int.class}),
           0);
       assertEntry(e, 1, "verify <target>");
       assertEquals("target", e.getComponentKey());
       assertEquals(int.class, e.getExpectedType());
       assertEquals(void.class, e.getActualType());
     }
    }
    public void testNullInstance(){
      final Container yan = createYanContainer();
      yan.registerStaticMethod(BaseContainerTestCase.class, "returnNull");
      testNullInstance(yan);
      yan.registerStaticMethod(BaseContainerTestCase.class, "returnNull", null);
      testNullInstance(yan);
      yan.registerStaticMethod(Object.class, BaseContainerTestCase.class, "returnNull");
      testNullInstance(yan);
      yan.registerStaticMethod(Object.class, BaseContainerTestCase.class, "returnNull", new Class[0]);
      testNullInstance(yan);
    }
   
    public static class PersonBean{
      private String name;
      public PersonBean(){}
      public PersonBean(String name){
        this.name = name;
      }
      public String getName(){return name;}
      public void setName(String name){
        this.name = name;
      }
    }
    public void testTypeMismatchForPropertyAndParameter()
    throws Exception{
      final Container yan = createYanContainer();
      yan.registerComponent(
          Components.ctor(PersonBean.class, new Class[]{String.class})
          .withArgument(0, Components.value(new int[0])));
      try{
        yan.verify();
        fail("should have type failed");
      }
      catch(ParameterTypeMismatchException e){
        assertEquals(2, e.getResolutionTrace().size());
        assertParameter(e, 0, Functions.ctor(PersonBean.class, new Class[]{String.class}),
            0);
        assertEquals(PersonBean.class, e.getComponentKey());
        assertEquals(0, e.getOrdinalPosition());
        assertEquals(String.class, e.getExpectedType());
        assertEquals(int[].class, e.getActualType());
      }
      //yan.verify();
      final HashMap props = new HashMap();
      props.put("name", Components.ctor(ArrayList.class, null));
      yan.registerComponent(Components.bean(PersonBean.class)
          .withProperties(props));
      try{
        yan.verify();
        fail("should have type failed");
      }
      catch(PropertyTypeMismatchException e){
        //e.printResolutionTrace(System.err);
        assertEquals(3, e.getResolutionTrace().size());
        assertProperty(e, 0, PersonBean.class, "name");
       
        assertEntry(e, 1, "bean");
        assertEntry(e, 2, "verify <class tests.jfun.yan.tck.BaseContainerTestCase$PersonBean>");
        assertEquals(PersonBean.class, e.getComponentKey());
        assertEquals("name", e.getPropertyKey());
        assertEquals(String.class, e.getExpectedType());
        assertEquals(ArrayList.class, e.getActualType());
      }
    }
    public void testContainerAsObject(){
      final Container yan1 = createYanContainer();
      final Container yan2 = createYanContainer();
      assertEquals(yan1, yan2);
      yan1.registerConstructor(Object.class);
      assertFalse(yan1.equals(yan2));
      yan1.getInstancesOfType(Object.class);
      yan1.unregisterComponent(Object.class);
      assertEquals(yan1, yan2);
      final HashMap map = new HashMap();
      map.put(yan1, yan1);
      assertEquals(yan1, map.get(yan1));
    }
    public class Person{
      private String name;
      private int age;
      private String nickname;
      private int id;
     
      Person(int id) {
        super();
        this.id = id;
      }
     
      public int getId() {
        return id;
      }
      public int getAge() {
        return age;
      }
      public void setAge(int age) {
        this.age = age;
      }
      public String getName() {
        return name;
      }
      public void setName(String name) {
        this.name = name;
      }
      public String getNickname() {
        return nickname;
      }
      public void setNickname(String nickname) {
        this.nickname = nickname;
      }
    }
   public  Person newPerson(int id){
      return new Person(id);
    }
   public Person newSuperman(int id){
     return new Person(id);
   }
   public interface IdFactory{
     public int newId();
   }
   public class IdGen implements IdFactory{
     private int seed = 0;
     public int newId(){return ++seed;}
   }
   protected Container getContainerWithPerson()
   throws Exception{
     try{
       Components.method(this, "newPerson").bean(
           new String[]{"name", "name2"});
       fail("should have failed with bad property");
     }
     catch(IllegalPropertyNameException e){
       assertEquals(0, e.getResolutionTrace().size());
       assertEquals("name2", e.getPropertyName());
       assertEquals(Person.class, e.getComponentType());
     }
     try{
       Components.bean(Components.method(this, "newPerson"),
       new String[]{"name", "name"});
       fail("should have failed with duplicate property name");
     }
     catch(IllegalArgumentException e){
       assertEquals("duplicate property name: name", e.getMessage());
     }
     try{
       Components.bean(Components.method(this, "newPerson"),
       new String[]{"name", "id"});
       fail("should have failed with non-writable property");
     }
     catch(NonWritablePropertyException e){
       assertTraceSize(e, 0);
       assertEquals("id", e.getPropertyName());
       assertEquals(Person.class, e.getComponentType());
     }
     Container yan = createYanContainer();
     Container yan2 = createYanContainer();
     yan.registerComponent("supermanref",
         Components.useKey("superman").bean()
         .withProperty("name", Components.useKey("personName"))
         .withProperty("age", Components.useType(Integer.class))
         .withProperty("nickname", Components.useContainer(yan2))
     );
     yan2.registerValue("Gandolf");
     try{
       yan.verify();
     }
     catch(UnresolvedComponentException e){
       assertTraceSize(e, 3);
       assertEntry(e, 0, "useKey <superman>");
       assertEntry(e, 1, "bean");
       assertEntry(e, 2, "verify <supermanref>");
       assertEquals("superman", e.getComponentKey());
     }
     yan.registerComponent("badsupermanref",
         Components.bean(
             Components.useKey("superman"),
             new String[]{"name","age","gender"}
         )
         .withProperty("name", Components.useKey("personName"))
         .withProperty("age", Components.useType(Integer.class))
         .withProperty("nickname", Components.useContainer(yan2))
        
     );
     yan.registerComponent("superman",
         Components.method(this, "newSuperman")
       );
     try{
       yan.registerValue(new Integer(-10));
       yan.getInstance("badsupermanref");
       fail("should have failed with IllegalPropertyNameException");
     }
     catch(IllegalPropertyNameException e){
       //e.printResolutionTrace();
       assertTraceSize(e, 2);
       assertEntry(e, 1, "getInstance <badsupermanref>");
       assertEntry(e, 0, "bean");
       //e.printResolutionTrace(System.err);
       assertEquals("gender", e.getPropertyName());
       assertEquals(Person.class, e.getComponentType());
       yan.unregisterComponentsOfType(Integer.class);
     }
     yan.unregisterComponent("superman");
     yan.unregisterComponent("supermanref");
     yan.unregisterComponent("badsupermanref");
     final Component anonymous_person = Components.bean(
         Components.method(this, "newPerson"),
         new String[]{"name","age"}
     )
     .withProperty("name", Components.useKey("personName"))
     .withProperty("age", Components.useType(Integer.class));
    
     yan.registerComponent(anonymous_person);
     final Component bad_person =          Components.bean(
         Components.value(null).subsume(Person.class),
         new String[]{"name","age"}
     )
     .withProperty("name", Components.useKey("personName"))
     .withProperty("age", Components.useType(Integer.class));
     yan.registerComponent("bad person",bad_person);
     try{
       yan.verify();
       fail("should have failed with IrresolveableArgumentException");
     }
     catch(IrresolveableArgumentException e){
       assertTraceSize(e, 3);
       assertParameter(e, 0, Functions.method(this, "newPerson"), 0);
       assertEntry(e, 1, ""+anonymous_person);
       assertEntry(e, 2, "verify <class tests.jfun.yan.tck.BaseContainerTestCase$Person>");
       assertEquals(0, e.getOrdinalPosition());
       assertEquals(Person.class, e.getComponentKey());
       assertEquals(int.class, e.getParameterType());
     }
     yan.registerComponent(Components.method(new IdGen(), "newId"));
     try{
       yan.verify();
       fail("should have failed with UnresolvedComponentException");
     }
     catch(UnresolvedComponentException e){
       assertEquals("personName", e.getComponentKey());
     }
     yan.registerValue("personName", "Yan");
     yan.registerValue(new Integer(16));
     yan.verify();
     try{
       yan.getInstance("bad person");
       fail("should have failed with null pointer");
     }catch(NullBeanObjectException e){
       assertTraceSize(e, 2);
       assertEntry(e, 0, ""+bad_person);
       assertEntry(e, 1, "getInstance <bad person>");
       assertEquals("null component", e.getMessage());
     }

     return yan;
   }
    public void testBeanWithSelectedProperties()
    throws Exception{
      Container yan = getContainerWithPerson();
      final Person person = (Person)yan.getInstance(Person.class);
      assertEquals("Yan", person.getName());
      assertEquals(16, person.getAge());
      assertSame(null, person.getNickname());
      assertEquals(1, person.getId());
    }
    public int expectArray(int[][] arr){return 1;}
    public void testBasics(){
      final Container yan = createYanContainer();
      yan.registerValue("abc");
      try{
        yan.getInstance("x");
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals("x", e.getComponentKey());
      }
      assertEquals(yan, yan);
      assertEquals(yan.toString(), yan.toString());
      yan.registerComponent("target", Components.method(this, "expectArray"));
      try{
        yan.verify();
        fail("should have failed with IrresolveableArgumentException");
      }
      catch(IrresolveableArgumentException e){
        assertEquals("target", e.getComponentKey());
        assertEquals(int[][].class, e.getParameterType());
        assertEquals(0, e.getOrdinalPosition());
        assertEquals("The #0 argument of type int[][] for component <target> is not resolveable", e.getMessage());
      }
      try{
        yan.registerComponent(Components.useKey("target"));
        fail("should have failed with UnknownComponentTypeException");
      }
      catch(UnknownComponentTypeException e){}
      try{
        yan.registerComponent(Components.useType(String.class));
        fail("should have failed with UnknownComponentTypeException");
      }
      catch(UnknownComponentTypeException e){
        assertTraceSize(e, 0);
      }
      yan.unregisterComponentsOfType(int.class);
      yan.verify();
      yan.registerComponent("target_also", Components.useKey("target"));
      try{
        yan.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals("target", e.getComponentKey());
      }
      yan.registerComponent("target",
          Components.method(this, "expectArray")
          .withArgument(0, Components.value(new int[10])));
      try{
        yan.verify();
        fail("should have failed with ParameterTypeMismatchException");
      }
      catch(ParameterTypeMismatchException e){
        assertTraceSize(e, 3);
        assertParameter(e, 0, Functions.method(this, "expectArray"), 0);
        assertEntry(e, 1, "useKey <target>");
        assertEntry(e, 2, "verify <target_also>");
        assertEquals("target_also", e.getComponentKey());
        assertEquals(int[][].class, e.getExpectedType());
        assertEquals(int[].class, e.getActualType());
        assertEquals(0, e.getOrdinalPosition());
        assertTrue(e.getMessage().startsWith(
            "type mismatch for The #0 parameter of component <target_also>")
          );
      }
      final Container yan2 = createYanContainer();
      yan.registerComponent("target", Components.useType(yan2, String.class));
      try{
        yan.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals(String.class, e.getComponentKey());
      }
      try{
        yan.getInstance("target_also");
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals(String.class, e.getComponentKey());
      }
      yan2.registerValue("target arrived!");
      assertEquals("target arrived!", yan.getInstance("target"));
    }
    public void testLifeycles()
    throws Throwable{
      final Container yan = new DefaultContainer();
      final Component real_engine =
        Components.useKey("real engine").singleton(new ThreadLocalScope());
      final DefaultLifecycleDescriptor desc = new DefaultLifecycleDescriptor();
      desc.setCloser(new Phase(desc.getCloser().getPhaseKey(), ExceptionHandlers.suppresser()));
      desc.setStopper(new Phase(desc.getStopper().getPhaseKey(), ExceptionHandlers.suppresser()));
      final DefaultLifecycleManager lm = new DefaultLifecycleManager(desc);
      final DefaultLifecycleManager.DefaultLifecycle lc = lm.newLifecycle()
      .starter("start")
      .stopper("stop")
      .initializer("initialize")
      .disposer("destroy");
      final Component engine_lc = lc.manage(real_engine);
      yan.registerComponent(CarEngine.class, engine_lc);
      /*
      yan.registerComponent(CarEngine.class, LifecycleDescriptor.instance(
          Components.useKey("real engine").singleton(new ThreadLocalScope()),
          ExceptionHandlers.suppresser())
          .starter("start")
          .stopper("stop")
          .initializer("initialize")
          .disposer("destroy")
          .get());
      */
      yan.registerConstructor("real engine", CarEngine.class);
      final Component sttfrc = Components.ctor(StatefulResource.class)
      .withArgument(0, Components.useType(CarEngine.class));
      yan.registerComponent(lc.manage(sttfrc));
      /*
      yan.registerComponent(LifecycleDescriptor.instance(
          Components.ctor(StatefulResource.class)
          .withArgument(0, Components.useType(CarEngine.class))
          , ExceptionHandlers.suppresser())
          .initializer("initialize")
          .disposer("destroy")
          .starter("start")
          .stopper("stop")
          .get());
      */
      final Component car_engine = yan.getComponentOfType(CarEngine.class);
      assertNull(car_engine.getType());
     
      final StatefulResource resource = (StatefulResource)yan.getInstanceOfType(StatefulResource.class);
      final CarEngine engine = (CarEngine)yan.getInstanceOfType(CarEngine.class);
      assertEquals(0, engine.getStarted());
      assertEquals(0, engine.getStopped());
      assertEquals(0, engine.getInit());
      assertEquals(0, engine.getDisposed());

      assertEquals(0, resource.getInitCount());
      assertEquals(0, resource.getDestroyedCount());
      //new DefaultLifecycle(yan).init();
      lm.init();
      assertEquals(0, engine.getStarted());
      assertEquals(0, engine.getStopped());
      assertEquals(1, engine.getInit());
      assertEquals(0, engine.getDisposed());

      assertEquals(1, resource.getInitCount());
      assertEquals(0, resource.getDestroyedCount());
      try{
        //new DefaultLifecycle(yan).start();
        lm.start();
        fail("should have failed with unsupported");
      }
      catch(UnsupportedOperationException e){
        assertEquals("start", e.getMessage());
      }
      assertEquals(1, engine.getStarted());
      assertEquals(0, engine.getStopped());
      assertEquals(1, engine.getInit());
      assertEquals(0, engine.getDisposed());

      assertEquals(1, resource.getInitCount());
      assertEquals(0, resource.getDestroyedCount());
      //new DefaultLifecycle(yan).init();
      lm.init();
      assertEquals(1, engine.getStarted());
      assertEquals(0, engine.getStopped());
      assertEquals(1, engine.getInit());
      assertEquals(0, engine.getDisposed());

      assertEquals(1, resource.getInitCount());
      assertEquals(0, resource.getDestroyedCount());
      //new DefaultLifecycle(yan).stop();
      lm.stop();
      assertEquals(1, engine.getStarted());
      assertEquals(1, engine.getStopped());
      assertEquals(1, engine.getInit());
      assertEquals(0, engine.getDisposed());

      assertEquals(1, resource.getInitCount());
      assertEquals(0, resource.getDestroyedCount());
      //final DefaultLifecycle lc = new DefaultLifecycle(yan);
      //lc.dispose();
      lm.dispose();
      assertEquals(1, engine.getStarted());
      assertEquals(1, engine.getStopped());
      assertEquals(1, engine.getInit());
      assertEquals(1, engine.getDisposed());

      assertEquals(1, resource.getInitCount());
      assertEquals(1, resource.getDestroyedCount());
     
      try{
        //lc.start();
        lm.start();
        fail("should have failed with unsupported");
      }
      catch(UnsupportedOperationException e){
        assertEquals("start", e.getMessage());
      }
      assertEquals(2, engine.getStarted());
      assertEquals(1, engine.getStopped());
      assertEquals(1, engine.getInit());
      assertEquals(1, engine.getDisposed());

      assertEquals(1, resource.getInitCount());
      assertEquals(1, resource.getDestroyedCount());

     
      //lc.stop();
      lm.stop();
      assertEquals(2, engine.getStarted());
      assertEquals(2, engine.getStopped());
      assertEquals(1, engine.getInit());
      assertEquals(1, engine.getDisposed());

      assertEquals(1, resource.getInitCount());
      assertEquals(1, resource.getDestroyedCount());
     
      /*
      lc.dispose();
      assertEquals(1, engine.getStarted());
      assertEquals(1, engine.getStopped());
      assertEquals(2, engine.getInit());
      assertEquals(2, engine.getDisposed());

      assertEquals(2, resource.getInitCount());
      assertEquals(2, resource.getDestroyedCount());
      */
    }
    /*
    public void testUnregister(){
      final Container yan = createYanContainer();
      yan.registerConstructor("string", String.class, null);
      assertEquals("", yan.getInstance("string"));
      yan.unregisterComponent("string");
      try{
        yan.getInstance("string");
        fail("should have failed with unresolved component");
      }
      catch(UnresolvedComponentException e){
        assertEquals("string", e.getComponentKey());
      }
      assertNull(yan.getComponentOfType(String.class));
      assertNull(yan.getComponent("string"));
    }*/
    public void testUseBadContainerKeyAndContainerType(){
      final Container yan = createYanContainer();
      yan.registerComponent("use_bad", Components.useKey(yan, "badkey"));
      try{
        yan.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals("badkey", e.getComponentKey());
        yan.unregisterComponent("use_bad");
      }
      yan.registerValue(char.class, new Character('a'));
      yan.registerComponent("use_badtype",
          Components.useType(createYanContainer(), char.class));
      try{
        yan.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals(char.class, e.getComponentKey());
        yan.unregisterComponent("use_badtype");
      }
    }
    public void testUseBadKeyAndType(){
      final Container yan = createYanContainer();
      yan.registerComponent("use_bad", Components.useKey("badkey"));
      try{
        yan.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals("badkey", e.getComponentKey());
        yan.unregisterComponent("use_bad");
      }
     
      yan.registerComponent("use_badtype",
          Components.useType(char.class));
      try{
        yan.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertEquals(char.class, e.getComponentKey());
        yan.unregisterComponent("use_badtype");
      }
    }
   
    public void testBadUseContainerWithArguments(){
      final Container yan1 = createYanContainer();
      final Container yan2 = createYanContainer();
      final Part ref2 = Components.useContainer(yan2);
      yan1.registerComponent("target",
          Components.ctor(NeedsTouchable.class)
          .withArguments(ref2));
      run_testBadUseContainerForArguments(yan1, yan2);
    }
    public void testBadUseContainerWithArgument(){
      final Container yan1 = createYanContainer();
      final Container yan2 = createYanContainer();
      final Part ref2 = Components.useContainer(yan2);
      yan1.registerComponent("target",
          Components.ctor(NeedsTouchable.class)
          .withArgument(0, ref2));
      run_testBadUseContainerForArguments(yan1, yan2);
    }
    private void run_testBadUseContainerForArguments(final Container yan1, final Container yan2){
      yan1.registerConstructor(SimpleTouchable.class);
      try{
        yan1.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertTraceSize(e, 2);
        assertParameter(e, 0, NeedsTouchable.class, 0);
        assertEntry(e, 1, "verify <target>");
        assertEquals(Touchable.class, e.getComponentKey());
      }
      try{
        yan1.getInstance("target");
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertTraceSize(e, 2);
        assertParameter(e, 0, NeedsTouchable.class, 0);
        assertEntry(e, 1, "getInstance <target>");
        assertEquals(Touchable.class, e.getComponentKey());
      }
      yan2.registerConstructor(WashableTouchable.class);
      yan1.verify();
      assertEquals(NeedsTouchable.class, yan1.getInstance("target").getClass());

    }

    public void testBadUseContainerWithProperties()
    throws Exception{
      final Container yan1 = createYanContainer();
      final Container yan2 = createYanContainer();
      final Part ref2 = Components.useContainer(yan2);
      yan1.registerComponent("target",
          Components.bean(PersonBean.class)
          .withProperties(ref2));
      //run_testBadUseContainerForProperties(yan1, yan2);
      run_testBadUseContainerForProperties(yan1, yan2);
    }
    public void testBadUseContainerWithProperty()
    throws Exception{
      final Container yan1 = createYanContainer();
      final Container yan2 = createYanContainer();
      final Part ref2 = Components.useContainer(yan2);
      yan1.registerComponent("target",
          Components.bean(PersonBean.class)
          .withProperty("name", ref2));
      //run_testBadUseContainerForProperties(yan1, yan2);
      run_testBadUseContainerForProperties(yan1, yan2);
    }
    public void testUseAll(){
      final Container yan = createYanContainer();
      yan.registerComponent("target", Components.useAll(String.class));
      yan.registerValue("abc");
      yan.registerValue("yet another", "cde");
      yan.verify();
      final java.util.List strs = (java.util.List)yan.getInstance("target");
      assertEquals(2, strs.size());
      assertEquals("abc", strs.get(0));
      assertEquals("cde", strs.get(1));
    }

    public void testUseAllInDifferentContainer(){
      final Container yan = createYanContainer();
      final Container yan2 = createYanContainer();
      yan.registerComponent("target", Components.useAll(yan2, String.class));
      yan.verify();
      yan2.registerValue("abc");
      yan.registerValue("yet another", "cde");
      yan.verify();
      final java.util.List strs = (java.util.List)yan.getInstance("target");
      assertEquals(1, strs.size());
      assertEquals("abc", strs.get(0));
      yan.verifyComponent(
          Components.useAll(yan2, String.class)
          );
      final java.util.List strs2 = (java.util.List)yan.instantiateComponent(
          Components.useAll(yan2, String.class)
          );
      assertEquals(1, strs2.size());
      assertEquals("abc", strs2.get(0));
     
    }
    public void testReturnState(){
      final Container yan = createYanContainer();
      yan.registerComponent(
          Components.returnState(Components.useKey("xxx").withState("hello")
          )
      );
      yan.verify();
      assertEquals("hello", yan.getInstance(Object.class));
    }
    public void testReturnType(){
      final Container yan = createYanContainer();
      yan.registerComponent(Class.class,
          Components.returnType(Components.useKey("xxx").cast(String.class))
      );
      yan.verify();
      assertEquals(String.class, yan.getInstance(Class.class));
    }
    public void testReturnVerification(){
      final Container yan = createYanContainer();
      yan.registerComponent(Class.class,
          Components.returnVerification(Components.useKey("xxx").cast(String.class))
      );
      try{
        yan.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        //e.printResolutionTrace(System.err);
        assertTraceSize(e, 4);
        assertEntry(e, 0, "useKey <xxx>");
        assertEntry(e, 1, "cast <useKey <xxx>> as java.lang.String");
        assertEntry(e, 2, "returnVerification <cast <useKey <xxx>> as java.lang.String>");
        assertEntry(e, 3, "verify <class java.lang.Class>");
        assertEquals("xxx", e.getComponentKey());
      }
      try{
        yan.getInstance(Class.class);
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertTraceSize(e, 4);
        assertEntry(e, 0, "useKey <xxx>");
        assertEntry(e, 1, "cast <useKey <xxx>> as java.lang.String");
        assertEntry(e, 2, "returnVerification <cast <useKey <xxx>> as java.lang.String>");
        assertEntry(e, 3, "getInstance <class java.lang.Class>");
        assertEquals("xxx", e.getComponentKey());
      }
      yan.registerValue("xxx",
          Components.useKey("bad").subsume(int.class).incomplete());
      yan.verify();
      assertEquals(String.class, yan.getInstance(Class.class));
    }


    private void run_testBadUseContainerForProperties(Container yan1, Container yan2){
      yan1.registerValue("abc");
      try{
        yan1.verify();
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        //e.printResolutionTrace();
        assertTraceSize(e, 3);
        assertProperty(e, 0, PersonBean.class, "name");
        assertEntry(e, 1, "bean");
        assertEntry(e, 2, "verify <target>");
        assertEquals(String.class, e.getComponentKey());
      }
      try{
        yan1.getInstance("target");
        fail("should have failed with UnresolvedComponentException");
      }
      catch(UnresolvedComponentException e){
        assertTraceSize(e, 3);
        assertProperty(e, 0, PersonBean.class, "name");
        assertEntry(e, 1, "bean");
        assertEntry(e, 2, "getInstance <target>");
        assertEquals(String.class, e.getComponentKey());
      }
      yan2.registerValue("7 yan");
      yan1.verify();
      assertEquals("7 yan", ((PersonBean)yan1.getInstance("target")).getName());

    }

   

    public static final class Civilian{
      private String dog;
      private String cat;
      private String wife = "do not need";
      private final int id;
      private final java.util.Date birthday;
      public Civilian(int id, final java.util.Date d){
        this.id = id;
        this.birthday = d;
      }
      public String getCat() {
        return cat;
      }
      public void setCat(String cat) {
        this.cat = cat;
      }
      public String getDog() {
        return dog;
      }
      public void setDog(String dog) {
        this.dog = dog;
      }
      public String getWife() {
        return wife;
      }
      public void setWife(String wife) {
        this.wife = wife;
      }
     
      public int getId() {
        return id;
      }
     
      public java.util.Date getBirthday() {
        return birthday;
      }
    }
    public void testBeanByName()
    throws Exception{
      final Container yan = createYanContainer();
      yan.registerValue("dog", "Bach");
      //yan.registerValue("cat", "Chopin");
      yan.registerComponent("civilian", Beans.byName(
          Components.ctor(Civilian.class)         
          .withDefaultArgument(0, Components.value(new Integer(-1)))
          //.optionalParameter(0)
          .optionalParameter(1)
          .bean()
          .optionalProperties()
          .withDefaultProperty("cat", Components.value("Chopin"))
          ));
     
      yan.registerComponent("civilian2", Beans.byName(Components.useKey("civilian")));
      yan.verify();
      Civilian civ = (Civilian)yan.getInstance("civilian");
      assertEquals("Bach", civ.getDog());
      assertEquals("Chopin", civ.getCat());
      assertEquals("do not need", civ.getWife());
      assertEquals(-1, civ.getId());
      assertNull(civ.getBirthday());
      civ = (Civilian)yan.getInstance("civilian2");
      assertEquals("Bach", civ.getDog());
      assertEquals("Chopin", civ.getCat());
      assertEquals("do not need", civ.getWife());
      assertEquals(-1, civ.getId());
      assertNull(civ.getBirthday());
    }
    public void testBeanByQualifiedName()
    throws Exception{
      try{
        final Container yan = createYanContainer();
        yan.registerValue("tests.jfun.yan.tck.BaseContainerTestCase$Civilian.dog", "Bach");
        yan.registerValue("tests.jfun.yan.tck.BaseContainerTestCase$Civilian.cat", "Chopin");
        yan.registerComponent("civilian", Beans.byQualifiedName(
            Components.ctor(Civilian.class)         
            .withDefaultArgument(0, Components.value(new Integer(-1)))
            .optionalParameters()
            .bean()
            .optionalProperties()
            ));
       
        yan.registerComponent("civilian2", Beans.byQualifiedName(Components.useKey("civilian")));
        yan.verify();
        Civilian civ = (Civilian)yan.getInstance("civilian");
        assertEquals("Bach", civ.getDog());
        assertEquals("Chopin", civ.getCat());
        assertEquals("do not need", civ.getWife());
        assertEquals(-1, civ.getId());
        assertNull(civ.getBirthday());
        civ = (Civilian)yan.getInstance("civilian2");
        assertEquals("Bach", civ.getDog());
        assertEquals("Chopin", civ.getCat());
        assertEquals("do not need", civ.getWife());
        assertEquals(-1, civ.getId());
        assertNull(civ.getBirthday());
      }
      catch(YanException e){
        e.printResolutionTrace();
        throw e;
      }
    }
    public void testMonadPlus(){
      final Container yan = createYanContainer();
      yan.registerComponent("a", Monad.mzero());
      try{
        yan.verify();
        fail("should have failed with ComponentResolutionException");
      }
      catch(ComponentResolutionException e){
        assertTraceSize(e, 2);
        assertEntry(e, 0, "fail <mzero>");
        assertEquals("mzero", e.getMessage());
      }
      yan.registerComponent("a", Monad.mzero().optional());
      try{
        yan.getInstance("a");
        fail("should have failed with DefaultingException");
      }
      catch(DefaultingException e){}
      yan.registerComponent("a", Components.useKey("b").option("hello world"));
      assertEquals("hello world", yan.getInstance("a"));
    }
    public void testContainerIsSerializable()throws Exception{
      getTouchableFromSerializedContainer();
    }
    private Container trans(Container yan)
    throws java.io.IOException, ClassNotFoundException{
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
     
      oos.writeObject(yan);
      ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
     
      return (Container) ois.readObject();
    }
    private Touchable getTouchableFromSerializedContainer()
    throws IOException, ClassNotFoundException {
      Container yan = createPicoContainerWithTouchableAndDependsOnTouchable();
      // Add a list too, using a constant parameter
      yan.registerComponent("list",
          Components.ctor(ArrayList.class, new Class[]{int.class})
          .withArgument(0, Components.value(10)));
     

      yan = trans(yan);
     
      DependsOnTouchable dependsOnTouchable = (DependsOnTouchable)
      yan.getInstanceOfType(DependsOnTouchable.class);
      assertNotNull(dependsOnTouchable);
      return (Touchable) yan.getInstanceOfType(Touchable.class);
    }
     
    public void testSerializedContainerCanRetrieveImplementation()
    throws Exception {
     
      Touchable touchable = getTouchableFromSerializedContainer();
     
      SimpleTouchable simpleTouchable = (SimpleTouchable) touchable;
     
      assertTrue(simpleTouchable.wasTouched);
    }
    public static final class GiveBean{
      private boolean awake = false;
      private String fname;
      private String middle_initial;
      private int age;
      public void giveAge(int age){
        this.age = age;
      }
      public void setName(String fn, char mi){
        this.fname = fn;
        this.middle_initial = ""+mi;
      }
      public void wakeup(){
        awake = true;
      }
     
      public int getAge() {
        return age;
      }
      public boolean isAwake() {
        return awake;
      }
      public String getFname() {
        return fname;
      }
      public String getMiddleInitial() {
        return middle_initial;
      }
      public void giveTime(long l){}
    }
    Component custProperty(Component c, final String giver){
      return c.followedBy(new ComponentBinder(){
        public Creator bind(Object obj){
          return Components.method(obj, giver);
        }
        public Verifiable verify(Class t){
          return Components.method(t, null, giver);
        }
        public Class bindType(Class t){
          return Functions.method(t, null, giver).getReturnType();
        }
      });
    }

    Component custProperties(Component c, String[] givers){
      Component r = c;
      for(int i=0;i<givers.length;i++){
        r = custProperty(r, givers[i]);
      }
      return r;
    }
    public void testGiveBean(){
      runTestGiveBean(custProperties(Components.ctor(GiveBean.class)
          , new String[]{"giveAge", "setName", "wakeup"}));
    }
    public void testGiveBeanWithVerify(){
      runTestGiveBean(Components.ctor(GiveBean.class).bind(gbean(
          new String[]{"giveAge", "setName", "wakeup"}))
      );
    }
    public void testUnsatisfiableGbean(){
      try{
        verifyGiveBean(Components.ctor(GiveBean.class).bind(gbean(
            new String[]{"giveAge", "setName", "wakeup", "giveTime"}))
            .label("gbean")
        );
        fail("should have failed with IrresolveableArgumentException");
      }
      catch(IrresolveableArgumentException e){
        //assertTraceSize(e, 4);
        assertEntry(e, 0,
            "parameter 0 of <public void tests.jfun.yan.tck.BaseContainerTestCase$GiveBean.giveTime(long)>");
        //e.printResolutionTrace();
      }
    }
    public void testFloatingMethod(){
      final Class type = Mtds.class;
      Container yan = createYanContainer();
      try{
        Components.static_method(type, "greet");
        fail("should have failed with IllegalArgumentException");
      }
      catch(IllegalArgumentException e){}
      try{
        Components.fun(Functions.instance_method(type, "getGreeting"));
        fail("should have failed with IllegalArgumentException");
      }
      catch(IllegalArgumentException e){}
      yan.registerComponent(Components.static_method(type, "instance"));
      yan.registerValue("Tom");
      yan.registerComponent("target",
          Components.fun(Functions.instance_method(type, "greet"))
          .withArgument(1, Components.value("Jerry")));
      assertEquals("hello Jerry, I am Tom", ""+yan.getInstance("target"));
      yan.registerComponent(Components.static_method(type, "instance"));
      yan.registerComponent("target",
          Components.fun(Functions.instance_method(type, "greet"))
          //.withArgument(0, Components.value("should not see this"))
          .withArgument(0, Components.useType(Mtds.class)
              //.withArgument(0,  Components.value("should not see me"))
              .withArgument(0,  Components.value("Jerry"))
              .withArgument(0,  Components.value("should not see me"))
          )
          );
      assertEquals("hello Tom, I am Jerry", ""+yan.getInstance("target"));

    }
    public static String tag(String prefix, int i){
      return prefix+i;
    }
    public void testComponentArgumentsShouldNotPropogateToParts(){
      final Container yan = createYanContainer();
      yan.registerValue("default prefix");
      yan.registerComponent(Components.value(1));
      final Component tag = Components.method(this, "tag");
      final Component target = tag
        .withArgument(0, Components.method(this, "tag"))
        .withArgument(1, Components.value(0));
      yan.registerComponent("target", target);
      final Object result = yan.getInstance("target");
      assertEquals("default prefix10", ""+result);
    }
    public void testUsePropertyCannotBeAppliedToTopLevel(){
      final Component use1 = Components.useProperty(String.class, "prop1", String.class)
        .withProperty("prop1", Components.value("hello"));
      final Container yan = createYanContainer();
      yan.registerComponent("target", use1);
      try{
        yan.verify();
      }
      catch(YanException e){
        assertTraceSize(e, 2);
        //e.printResolutionTrace();
        assertEquals("useProperty can only be used for parameter or property",
            e.getMessage());
      }
      try{
        yan.instantiateComponent(use1);
        //yan.getInstance("target");
      }
      catch(YanException e){
        //e.printResolutionTrace();
        assertTraceSize(e, 2);
        //e.printResolutionTrace();
        assertEquals("useProperty can only be used for parameter or property",
            e.getMessage());
      }

    }
    public void testUseArgumentCannotBeAppliedToTopLevel(){
      final Component use1 = Components.useArgument(Functions.ctor(String.class,null),
          0, String.class)
        .withArgument(0, Components.value("hello"));
      final Container yan = createYanContainer();
      yan.registerComponent("target", use1);
      try{
        yan.verify();
      }
      catch(YanException e){
        assertTraceSize(e, 2);
        //e.printResolutionTrace();
        assertEquals("useArgument can only be used for parameter or property",
            e.getMessage());
      }
      try{
        yan.getInstances();
      }
      catch(YanException e){
        assertTraceSize(e, 2);
        //e.printResolutionTrace();
        assertEquals("useArgument can only be used for parameter or property",
            e.getMessage());
      }

    }
    public void testPropertiesAndArgumentsApplyToBothBeanComponentAndBaseComponent()
    throws Exception{
      final Container yan = createYanContainer();
      final Component c1 = Components.ctor(MyBean.class, null);
      final Component c2 = c1.bean(new String[]{"1","nums"})
      .withProperties(new String[]{"1","nums"},
          new Component[]{Components.value(true),
          Components.value(new int[]{1,2,3})
      })
      .bean(new String[]{"name","short"});
      final Component target = c2
      .withProperties(new String[]{"1","name","short","nums"},
          new Component[]{Components.value(false),
          Components.value("Ent"),
          Components.value((short)-1),
          Components.value(new int[]{1,2,3,4})});
      yan.verifyComponent(target);
      final MyBean mb = (MyBean)yan.instantiateComponent(target);
      assertTrue(mb.is1());
      assertEquals("Ent", mb.getName());
      assertEquals((short)-1, mb.getShort());
      assertEquals(3, mb.getNums().length);
    }
    public void testConstructorParametesUsedAsMandatoryProperties()
    throws Exception{
      final Component c1 = Components.ctor(CopyCommand.class);
      final Component cc = Beans.beanComponent(c1, new String[]{"source","dest"});

      final Container yan = createYanContainer();
      verifyPropertyNotResolved(yan, cc);
      yan.registerComponent(boolean.class, Components.value(true));
      verifyPropertyNotResolved(yan, cc);
      //System.out.println();
      assertComponentInfo(c1, 2,
          "0=class java.lang.String, 1=class java.lang.String", "",
          tests.jfun.models.CopyCommand.class
          );
      assertComponentInfo(cc, 0, "",
          "source=class java.lang.String, dest=class java.lang.String, force=boolean, options=class java.lang.String",
          tests.jfun.models.CopyCommand.class
          );
      //System.out.println(jfun.yan.etc.Introspector.getComponentInfo(cc));
      //System.out.println(jfun.yan.etc.Introspector.getExpectedProperties(c1));
      final Component cc_src = cc.withProperty("source", Components.value("d:/"));
      //System.out.println(jfun.yan.etc.Introspector.getComponentInfo(cc_src));
      assertComponentInfo(cc_src, 0, "",
          "dest=class java.lang.String, force=boolean, options=class java.lang.String",
          tests.jfun.models.CopyCommand.class
          );     
      verifyPropertyNotResolved(yan, cc_src);
      final Component cc_src_dst = cc_src.withProperty("dest", Components.value("e:/abc"));
      //System.out.println(jfun.yan.etc.Introspector.getComponentInfo(cc_src_dst));
      assertComponentInfo(cc_src_dst, 0, "",
          "force=boolean, options=class java.lang.String",
          tests.jfun.models.CopyCommand.class
          );
      final CopyCommand cm = (CopyCommand)yan.instantiateComponent(cc_src_dst);
      assertEquals("d:/", cm.getSource());
      assertEquals("e:/abc", cm.getDest());
      assertTrue(cm.isForce());
      assertEquals("", cm.getOptions());
    }
    private void assertComponentInfo(
        Component c, int pnum, String params, String props, Class type){
      final jfun.yan.ComponentInfo info =
        jfun.yan.Introspector.getComponentInfo(c);
      assertEquals(pnum, info.getParameterCount());
      assertEquals("type = " + jfun.util.Misc.getTypeName(type)
          +"\nparameters = {" + params + "}"
          +"\nproperties = {" + props + "}", info.toString());
    }
    private void verifyPropertyNotResolved(Container yan, Component cc){
      try{
        yan.instantiateComponent(cc);
        fail("should have failed");
      }
      catch(IrresolveablePropertyException e){}
    }
    public static class MultiBean{
      public static class InnerBean{
       
        private boolean active;
        public java.util.List getList(){
          return new ArrayList();
        }
        public Object getListAsObject(){
          return new ArrayList();
        }
        public void setActive(boolean a){
          this.active = a;
        }
        public boolean isActive(){
          return active;
        }
      }
      private InnerBean inner;
      private InnerBean[] inners = new InnerBean[2];
      public InnerBean getInner(){
        return inner;
      }
      public void setInner(InnerBean inner){
        this.inner = inner;
      }
      public Object getInnerAsObject(){
        return inner;
      }
      public InnerBean[] getInners(){return inners;}
      public void setInners(InnerBean[] inners){
        this.inners = inners;
      }
      public InnerBean getInners(int i){
        return inners[i];
      }
      public void setInners(int i, InnerBean inner){
        inners[i] = inner;
      }
    }
    public void testHigherOrderMethod()
    throws Exception{
      final Component c = Components.ctor(ArrayList.class, null);
      testHigherOrderMethod(c);
      testHigherOrderMethod(c.cast(null));
      final Component nested = Components.ctor(MultiBean.class);
      testHigherOrderMethod(
          nested.bean(new String[]{"inner"})
          .withProperty("inner",
              Components.ctor(MultiBean.InnerBean.class)
          )
          .method("getInner").method("getList")
      );

      testHigherOrderMethod(
          nested.cast(null).bean(new String[]{"inner"})
          .withProperty("inner",
              Components.ctor(MultiBean.InnerBean.class)
          )
          .method("getInner").method("getList")
      );
      testHigherOrderMethod(
          nested.cast(null).bean(new String[]{"inner"})
          .withProperty("inner",
              Components.ctor(MultiBean.InnerBean.class)
          )
          .method("getInner").method("getListAsObject")
      );
      try{
        testHigherOrderMethod(
            nested.bean(new String[]{"inner"})
            .withProperty("inner",
                Components.ctor(MultiBean.InnerBean.class)
            )
            .method("getInner").method("getListAsObject")
        );
        fail("should have failed with IllegalArgumentException");
      }
      catch(IllegalArgumentException e){
        assertEquals("method java.lang.Object.size not found", e.getMessage());
      }
     
     
      //test nested bean
      testHigherOrderMethod(
          nested.bean(new String[]{"inner"})
          .withProperty("inner",
              Components.ctor(MultiBean.InnerBean.class)
          )
          .getter("inner").getter("list")
      );
      testHigherOrderMethod(
          nested.setter("inner")
          .withArgument(0,
              Components.ctor(MultiBean.InnerBean.class)
          )
          .getter("inner").getter("list")
      );
      testHigherOrderMethod(
          nested.cast(null).bean(new String[]{"inner"})
          .withProperty("inner",
              Components.ctor(MultiBean.InnerBean.class)
          )
          .getter("inner").getter("list")
      );
      testHigherOrderMethod(
          nested.cast(null).setter("inner")
          .withArgument(0,
              Components.ctor(MultiBean.InnerBean.class)
          )
          .getter("inner").getter("list")
      );
      try{
        testHigherOrderMethod(
            nested.bean(new String[]{"inner"})
            .withProperty("inner",
                Components.ctor(MultiBean.InnerBean.class)
            )
            .getter("inner").getter("listAsObject")
        );
        fail("should have failed with IllegalArgumentException");
      }
      catch(IllegalArgumentException e){
        assertEquals("method java.lang.Object.size not found", e.getMessage());
      }
      testHigherOrderMethod(
          nested.cast(null).bean(new String[]{"inner"})
          .withProperty("inner",
              Components.ctor(MultiBean.InnerBean.class)
          )
          .getter("innerAsObject").method("getListAsObject")
      );
      testHigherOrderMethod(
          nested.cast(null).bean(new String[]{"inner"})
          .withProperty("inner",
              Components.ctor(MultiBean.InnerBean.class)
          )
          .getter("innerAsObject").getter("listAsObject")
      );
      try{
        testHigherOrderMethod(
            nested.bean(new String[]{"inner"})
            .withProperty("inner",
                Components.ctor(MultiBean.InnerBean.class)
            )
            .getter("innerAsObject").getter("list")
        );
        fail("should have failed with IllegalArgumentException");
      }
      catch(jfun.util.beans.NoSuchPropertyException e){
        assertEquals("property <java.lang.Object.list> cannot be found", e.getMessage());
        assertEquals("list", e.getPropertyName());
        assertEquals(Object.class, e.getBeanClass());
      }
    }

    private Component innerInstance(boolean a)
    throws IntrospectionException{
      return Components.ctor(MultiBean.InnerBean.class).setter("active")
        .withArgument(0, Components.value(a));
    }
    public void testHigherOrderMethodWithIndexedProperties()
    throws Exception{
      final Component nested = Components.ctor(MultiBean.class);
      final Component inner1 = innerInstance(true);
      final Component inner2 = innerInstance(false);
      Component data = nested.setter("inner")
      .withArgument(0, inner1)  
      .setter("inners", 0)
      .withArgument(0, inner2)
      .setter("inners", 1)
      .withArgument(0, innerInstance(true));
      testHigherOrderMethod(
          data
          .getter("inners", 0).getter("list")
      );
      assertBool(data.getter("inners", 0).getter("active"), false);
      assertBool(data.getter("inners", 1).getter("active"), true);
     
     
      data = nested.cast(null).setter("inner")
      .withArgument(0, inner1)  
      .setter("inners", 0)
      .withArgument(0, inner2)
      .setter("inners", 1)
      .withArgument(0, innerInstance(true))
      ;
      testHigherOrderMethod(
          data
          .getter("inner").getter("list")
      );
      assertBool(data.getter("inners", 0).getter("active"), false);
      assertBool(data.getter("inners", 1).getter("active"), true);

    }
    public void testComponentManagedByMoreThanOneLifecycleManagers()
    throws Throwable{
      DefaultLifecycleManager man1 = new DefaultLifecycleManager();
      DefaultLifecycleManager man2 = new DefaultLifecycleManager();
      Component c = Components.ctor(Automobile.class);
      c = man1.newLifecycle()
        .starter("start1")
        .stopper("stop1")
        .manage(c);
      c = man2.newLifecycle()
        .starter("start2")
        .stopper("stop2")
        .manage(c);
      Container yan = createYanContainer();
      yan.registerComponent("target", c);
      Automobile a = (Automobile)yan.getInstance("target");
      assertFalse(a.isRunning1());
      assertFalse(a.isRunning2());
      man1.start();
      assertTrue(a.isRunning1());
      assertFalse(a.isRunning2());
      man2.start();
      assertTrue(a.isRunning1());
      assertTrue(a.isRunning2());  
      man1.stop();
      assertFalse(a.isRunning1());
      assertTrue(a.isRunning2());
      man2.stop();
      assertFalse(a.isRunning1());
      assertFalse(a.isRunning2());
    }
    public void testParameterCustomizationShouldNotPropogateToTheNextLevel()
    throws Exception{
      Container yan = this.createYanContainer();
      yan.registerValue("autowired");
      final Component manual = Components.value("manualwired");
      final Component cc1 = Components.ctor(Echo.class).method("newInstance")
        .withArgument(0, manual);
      final Component cc2 = Components.ctor(Echo.class).method("add")
        .withArgument(0, manual);
      final Component cc3 = Components.static_method(Echo.class, "newInstance")
      .method("add")
      .withArgument(0, manual);
      final Component cc4 = Components.static_method(Echo.class, "newInstance")
      .bean()
      .method("add")
      .withArgument(0, manual);
      final Component cc5 = Components.static_method(Echo.class, "newInstance")
      .bean()
      .withArgument(0, manual)
      .method("add")
      .withArgument(0, manual);

      yan.registerComponent("cc1", cc1);
      yan.registerComponent("cc2", cc2);
      yan.registerComponent("cc3", cc3);
      yan.registerComponent("cc4", cc4);
      yan.registerComponent("cc5", cc5);
      yan.registerComponent("cc6", cc4.singleton());
      assertEquals("manualwired", yan.getInstance("cc1").toString());
      assertEquals("autowiredmanualwired", yan.getInstance("cc2").toString());
      assertEquals("autowiredmanualwired", yan.getInstance("cc3").toString());
      assertEquals("autowiredmanualwired", yan.getInstance("cc4").toString());
      assertEquals("manualwiredmanualwired", yan.getInstance("cc5").toString());
      assertEquals("autowiredmanualwired", yan.getInstance("cc6").toString());
    }
    private void assertBool(Component c, boolean a){
      final Container yan = createYanContainer();
      yan.registerComponent("target", c);
      final Boolean result = (Boolean)yan.getInstance("target");
      assertEquals(a, result.booleanValue());
    }
    private void testHigherOrderMethod(Component c)
    throws Exception{
      try{
        final Component sz0 = c.method("size");
        final Container yan = createYanContainer();
        yan.registerComponent("list", c);
        yan.registerComponent("size", sz0);
        assertEquals(new Integer(0), yan.getInstance("size"));
        final Component sz1 = c.followedBy(new Binder(){
          public Creator bind(Object l){
            return Components.value(l).method("add", new Class[]{Object.class})
              .withArgument(0, Components.useKey("elem1"));
          }
        }).method("size", null);
        yan.registerValue("elem1", "val1");
        yan.registerComponent("size", sz1);
        assertEquals(new Integer(1), yan.getInstance("size"));
       
        final Component sz2 = c.followedBy(new Binder(){
          public Creator bind(Object l){
            final Component adder =
              Components.value(l).method("add", new Class[]{Object.class});
           
            return adder
              .withArgument(0, Components.useKey("elem1"))
              .seq(adder.withArgument(0, Components.useKey("elem2")));
          }
        }).method(java.util.List.class.getMethod("size", new Class[0]));
        yan.registerValue("elem2", "val2");
        yan.registerComponent("size", sz2);
        assertEquals(new Integer(2), yan.getInstance("size"));
        assertFalse(sz0.equals(sz1));
        assertFalse(sz1.equals(sz0));
        assertFalse(sz0.equals(sz2));
        assertFalse(sz2.equals(sz0));
        assertFalse(sz2.equals(sz1));
        assertFalse(sz1.equals(sz2));
        assertHash(sz0);
        assertHash(sz1);
        assertHash(sz2);
      }
      catch(YanException e){
        e.printResolutionTrace();
        throw e;
      }
    }

    protected void assertError(Component c, Class etype, String msg)
    throws Throwable{
      Container yan = createYanContainer();
      yan.registerComponent("target", c);
      try{
        yan.getInstance("target");
      }
      catch(Throwable e){
        if(etype.isInstance(e)){
          assertEquals(msg, e.getMessage());
          return;
        }
        else{
          if(e instanceof YanException){
            final Throwable cause = ((YanException)e).getCause();
            if(cause!=null){
              if(etype.isInstance(cause)){
                assertEquals(cause.getClass().getName()+": " + msg, e.getMessage());
                return;
              }
            }
          }
          throw e;
        }
      }
      fail("should have failed with: "+msg);
    }
    protected void assertResult(Component c, Object val){
      Container yan = createYanContainer();
      yan.registerComponent("target", c);
      assertEquals(val, yan.getInstance("target"));
    }
    private void assertHash(Object obj){
      final HashMap map = new HashMap();
      assertEquals(obj, obj);
      map.put(obj, obj);
      assertEquals(obj, map.get(obj));
    }
    private Container getGbeanContainer(Component gb){
      Container yan = createYanContainer();
      yan.registerValue("firstname", "Jack");
      //yan.registerValue("lastname", "Nicolson");
      yan.registerValue("middle", new Character('M'));
      yan.registerValue("age", new Integer(10));

      yan.registerComponent("target", gb);
      return yan;
    }
    private void runTestGiveBean(Component gb){
      final Container yan = getGbeanContainer(gb);
      yan.verify();
      final GiveBean target = (GiveBean)yan.getInstance("target");
      assertEquals("Jack", target.getFname());
      assertEquals("M", target.getMiddleInitial());
      assertEquals(10, target.getAge());
      assertTrue(target.isAwake());
    }
    private void verifyGiveBean(Component gb){
      getGbeanContainer(gb).verify();
    }
    private ComponentBinder gbean(final String[] givers){
      return new ComponentBinder(){
        public Creator bind(Object v){
          return giveProperties(v, givers);
        }
        public Verifiable verify(Class t){
          return verifyProperties(t, givers);
        }
        public Class bindType(Class t){
          return void.class;
        }
      };
    }
    private Creator giveProperties(Object v, String[] givers){
      Component r = Components.value(v);
      for(int i=0; i<givers.length; i++){
        r = r.followedBy(Components.method(v, givers[i]));
      }
      return r;
    }
    private Verifiable verifyProperties(Class t, String[] givers){
      Component r = Components.value(null).cast(t);
      for(int i=0; i<givers.length; i++){
        r = r.followedBy(
            Components.method(t, null, givers[i])
        );
      }
      return r;
    }
}
TOP

Related Classes of tests.jfun.yan.tck.BaseContainerTestCase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.