/*
* Grapht, an open source dependency injector.
* Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
* Copyright 2010-2014 Regents of the University of Minnesota
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.grouplens.grapht.solver;
import org.grouplens.grapht.CachePolicy;
import org.grouplens.grapht.annotation.AnnotationBuilder;
import org.grouplens.grapht.reflect.*;
import org.grouplens.grapht.reflect.internal.*;
import org.grouplens.grapht.reflect.internal.types.*;
import org.junit.Assert;
import org.junit.Test;
import java.lang.annotation.Annotation;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
public class BindRuleTest {
@Test
public void testEquals() {
// test various permutations of bind rule configurations
TypeA instance = new TypeA();
BindRule b1 = BindRuleBuilder.create()
.setDependencyType(TypeA.class)
.setImplementation(TypeA.class)
.setCachePolicy(CachePolicy.NO_PREFERENCE)
.setQualifierMatcher(Qualifiers.matchAny())
.setTerminal(false)
.build();
BindRule b2 = BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(new InstanceSatisfaction(instance)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
BindRule b3 = BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.match(RoleA.class)).setTerminal(false).build();
Assert.assertEquals(b1, BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build());
Assert.assertFalse(b1.equals(BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeB.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build()));
Assert.assertFalse(b1.equals(BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(true).build()));
Assert.assertFalse(b1.equals(BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.NEW_INSTANCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build()));
Assert.assertEquals(b2, BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(new InstanceSatisfaction(instance)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build());
Assert.assertFalse(b2.equals(BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(new ProviderClassSatisfaction(ProviderA.class)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build()));
Assert.assertEquals(b3, BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.match(RoleA.class)).setTerminal(false).build());
Assert.assertFalse(b3.equals(BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.match(RoleD.class)).setTerminal(false).build()));
}
@Test
public void testPrimitiveMatch() throws Exception {
// test boxing/unboxing of types
doMatchTest(Integer.class, null, int.class, null, true);
doMatchTest(int.class, null, Integer.class, null, true);
}
@Test
public void testExactClassNoRoleMatch() throws Exception {
doMatchTest(TypeA.class, null, TypeA.class, null, true);
}
@Test
public void testExactClassExactRoleMatch() throws Exception {
doMatchTest(TypeA.class, RoleA.class, TypeA.class, RoleA.class, true);
}
@Test
public void testSubclassNoMatch() throws Exception {
doMatchTest(TypeB.class, null, TypeA.class, null, false);
}
@Test
public void testNoInheritenceNoMatch() throws Exception {
doMatchTest(TypeC.class, null, TypeA.class, null, false);
doMatchTest(TypeA.class, null, TypeB.class, null, false);
}
@Test
public void testNoRoleInheritenceNoMatch() throws Exception {
doMatchTest(TypeA.class, RoleA.class, TypeA.class, RoleD.class, false);
}
@Test
public void testSuperRoleNoMatch() throws Exception {
doMatchTest(TypeA.class, RoleA.class, TypeA.class, RoleB.class, false);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void doMatchTest(Class desireType, Class<? extends Annotation> desireRole,
Class bindType, Class<? extends Annotation> bindRole,
boolean expected) throws Exception {
QualifierMatcher br = (bindRole == null ? Qualifiers.matchAny() : Qualifiers.match(bindRole));
Annotation dr = (desireRole == null ? null : new AnnotationBuilder(desireRole).build());
BindRule rule = BindRuleBuilder.create().setDependencyType(bindType).setImplementation(bindType).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(br).setTerminal(false).build();
ReflectionDesire desire = new ReflectionDesire(new MockInjectionPoint(desireType, dr, false));
Assert.assertEquals(expected, rule.matches(desire));
}
@Test
public void testNullable() throws Exception {
doNullableTest(false, false, true);
doNullableTest(true, false, true);
doNullableTest(false, true, true);
doNullableTest(true, true, true);
}
private void doNullableTest(boolean nullableDesire, boolean nullableSatisfaction, boolean expected) throws Exception {
InjectionPoint injectPoint = new MockInjectionPoint(TypeA.class, nullableDesire);
Satisfaction satisfaction = (nullableSatisfaction ? new NullSatisfaction(TypeA.class)
: new ClassSatisfaction(TypeA.class));
BindRule rule = BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(satisfaction).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(true).build();
ReflectionDesire desire = new ReflectionDesire(injectPoint);
Assert.assertEquals(expected, rule.matches(desire));
}
@Test
public void testSatisfiableClassBindRuleSuccess() throws Exception {
BindRule rule = BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(Satisfactions.type(TypeB.class)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
ReflectionDesire desire = new ReflectionDesire(new MockInjectionPoint(TypeA.class, false));
Assert.assertTrue(rule.matches(desire));
ReflectionDesire applied = (ReflectionDesire) rule.apply(desire);
Assert.assertNotNull(applied.getSatisfaction());
Assert.assertEquals(ClassSatisfaction.class, applied.getSatisfaction().getClass());
Assert.assertEquals(TypeB.class, ((ClassSatisfaction) applied.getSatisfaction()).getErasedType());
}
@Test
public void testUnsatisfiableClassBindRuleSuccess() throws Exception {
BindRule rule = BindRuleBuilder.create().setDependencyType(InterfaceA.class).setImplementation(InterfaceA.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
ReflectionDesire desire = new ReflectionDesire(new MockInjectionPoint(InterfaceA.class, false));
Assert.assertTrue(rule.matches(desire));
ReflectionDesire applied = (ReflectionDesire) rule.apply(desire);
Assert.assertNull(applied.getSatisfaction());
Assert.assertEquals(InterfaceA.class, applied.getDesiredType());
}
@Test
public void testInstanceBindRuleSuccess() throws Exception {
TypeA instance = new TypeB();
BindRule rule = BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(Satisfactions.instance(instance)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
ReflectionDesire desire = new ReflectionDesire(new MockInjectionPoint(TypeA.class, false));
Assert.assertTrue(rule.matches(desire));
Desire applied = rule.apply(desire);
Assert.assertNotNull(applied.getSatisfaction());
Assert.assertEquals(InstanceSatisfaction.class, applied.getSatisfaction().getClass());
Assert.assertEquals(instance, ((InstanceSatisfaction) applied.getSatisfaction()).getInstance());
}
@Test
public void testNullInstanceBindRuleSuccess() throws Exception {
BindRule rule = BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(Satisfactions.nullOfType(TypeA.class)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
ReflectionDesire desire = new ReflectionDesire(new MockInjectionPoint(TypeA.class, true));
Assert.assertTrue(rule.matches(desire));
Desire applied = rule.apply(desire);
Assert.assertNotNull(applied.getSatisfaction());
Assert.assertEquals(NullSatisfaction.class, applied.getSatisfaction().getClass());
}
@Test
public void testProviderClassBindRuleSuccess() throws Exception {
BindRule rule = BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(Satisfactions.providerType(ProviderA.class)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
ReflectionDesire desire = new ReflectionDesire(new MockInjectionPoint(TypeA.class, false));
Assert.assertTrue(rule.matches(desire));
Desire applied = rule.apply(desire);
Assert.assertNotNull(applied.getSatisfaction());
Assert.assertEquals(ProviderClassSatisfaction.class, applied.getSatisfaction().getClass());
Assert.assertEquals(ProviderA.class, ((ProviderClassSatisfaction) applied.getSatisfaction()).getProviderType());
}
@Test
public void testProviderInstanceBindRuleSuccess() throws Exception {
ProviderA instance = new ProviderA();
BindRule rule = BindRuleBuilder.create().setDependencyType(TypeA.class).setSatisfaction(Satisfactions.providerInstance(instance)).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
ReflectionDesire desire = new ReflectionDesire(new MockInjectionPoint(TypeA.class, false));
Desire applied = rule.apply(desire);
Assert.assertNotNull(applied.getSatisfaction());
Assert.assertEquals(ProviderInstanceSatisfaction.class, applied.getSatisfaction().getClass());
Assert.assertEquals(instance, ((ProviderInstanceSatisfaction) applied.getSatisfaction()).getProvider());
}
@Test
public void testCopyBuilder() {
BindRule b1 = BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.NO_PREFERENCE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
BindRule b2 = BindRuleBuilder.create().setDependencyType(TypeA.class).setImplementation(TypeA.class).setCachePolicy(CachePolicy.MEMOIZE).setQualifierMatcher(Qualifiers.matchAny()).setTerminal(false).build();
assertThat(b1.newCopyBuilder()
.build(),
equalTo(b1));
assertThat(b1.newCopyBuilder()
.setCachePolicy(CachePolicy.MEMOIZE)
.build(),
equalTo(b2));
}
}