/*****************************************************************************
* 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;
}
}