1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht.reflect.internal;
21
22 import com.google.common.collect.Maps;
23 import com.google.common.collect.SetMultimap;
24 import org.grouplens.grapht.*;
25 import org.grouplens.grapht.BindingFunctionBuilder.RuleSet;
26 import org.grouplens.grapht.graph.DAGEdge;
27 import org.grouplens.grapht.graph.DAGNode;
28 import org.grouplens.grapht.reflect.Desire;
29 import org.grouplens.grapht.reflect.Desires;
30 import org.grouplens.grapht.reflect.InjectionPoint;
31 import org.grouplens.grapht.reflect.internal.types.*;
32 import org.grouplens.grapht.solver.DefaultDesireBindingFunction;
33 import org.grouplens.grapht.solver.DefaultInjector;
34 import org.junit.Assert;
35 import org.junit.Test;
36
37 import javax.inject.Provider;
38 import java.util.Map;
39
40 import static org.hamcrest.Matchers.hasKey;
41 import static org.hamcrest.Matchers.hasSize;
42 import static org.junit.Assert.assertThat;
43
44 public class ReflectionInjectionTest {
45 @Test
46 public void testProviderCycleInjection() throws Exception {
47 InjectorBuilder b = InjectorBuilder.create().setProviderInjectionEnabled(true);
48 Injector i = b.build();
49
50 i.getInstance(CycleA.class);
51 DAGNode<Component,Dependency> root = ((DefaultInjector) i).getSolver().getGraph();
52
53 assertThat(root.getReachableNodes(), hasSize(3 + 1));
54
55 assertThat(root.getOutgoingEdges(), hasSize(1));
56 DAGNode<Component, Dependency> anode = root.getOutgoingEdges().iterator().next().getTail();
57 Assert.assertEquals(CycleA.class, anode.getLabel().getSatisfaction().getErasedType());
58
59 Assert.assertEquals(1, anode.getOutgoingEdges().size());
60 DAGNode<Component, Dependency> bnode = anode.getOutgoingEdges().iterator().next().getTail();
61 Assert.assertEquals(CycleB.class, bnode.getLabel().getSatisfaction().getErasedType());
62
63 Assert.assertEquals(1, bnode.getOutgoingEdges().size());
64 DAGNode<Component, Dependency> pnode = bnode.getOutgoingEdges().iterator().next().getTail();
65 Assert.assertEquals(Provider.class, pnode.getLabel().getSatisfaction().getErasedType());
66
67
68 Assert.assertEquals(0, pnode.getOutgoingEdges().size());
69
70 SetMultimap<DAGNode<Component,Dependency>,DAGEdge<Component, Dependency>> backEdges = ((DefaultInjector) i).getSolver().getBackEdges();
71 assertThat(backEdges.entries(), hasSize(1));
72 DAGEdge<Component, Dependency> edge = backEdges.values().iterator().next();
73 Assert.assertSame(anode, edge.getTail());
74 }
75
76 @Test
77 public void testTypeCInjectionWithDefaults() throws Exception {
78
79
80 Desire rootDesire = Desires.create(null, TypeC.class, false);
81 DefaultInjector r = new DefaultInjector(DefaultDesireBindingFunction.create());
82
83 TypeC instance = r.getInstance(TypeC.class);
84 Assert.assertEquals(5, instance.getIntValue());
85 Assert.assertNotNull(instance.getInterfaceA());
86 Assert.assertTrue(instance.getInterfaceA() instanceof TypeB);
87 Assert.assertSame(instance.getInterfaceA(), instance.getTypeA());
88 Assert.assertNotNull(instance.getInterfaceB());
89 Assert.assertTrue(instance.getInterfaceB() instanceof TypeB);
90 Assert.assertSame(instance.getInterfaceB(), instance.getTypeB());
91
92
93 Assert.assertSame(instance, r.getInstance(TypeC.class));
94
95 DAGNode<Component, Dependency> resolvedRoot =
96 r.getSolver().getGraph().getOutgoingEdgeWithLabel(Dependency.hasInitialDesire(rootDesire)).getTail();
97 assertThat(resolvedRoot.getOutgoingEdges(),
98 hasSize(5));
99
100 Map<InjectionPoint, DAGNode<Component, Dependency>> deps = Maps.newHashMap();
101 for (DAGEdge<Component, Dependency> e: resolvedRoot.getOutgoingEdges()) {
102 ReflectionDesire d = (ReflectionDesire) e.getLabel().getInitialDesire();
103
104 if (d.getInjectionPoint().equals(TypeC.CONSTRUCTOR)) {
105
106 Assert.assertFalse(deps.containsKey(TypeC.CONSTRUCTOR));
107 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof InstanceSatisfaction);
108 Assert.assertEquals(5, ((InstanceSatisfaction) e.getTail().getLabel().getSatisfaction()).getInstance());
109 deps.put(TypeC.CONSTRUCTOR, e.getTail());
110 } else if (d.getInjectionPoint().equals(TypeC.INTERFACE_A)) {
111
112 Assert.assertFalse(deps.containsKey(TypeC.INTERFACE_A));
113 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof ProviderClassSatisfaction);
114 Assert.assertEquals(ProviderA.class, ((ProviderClassSatisfaction) e.getTail().getLabel().getSatisfaction()).getProviderType());
115 deps.put(TypeC.INTERFACE_A, e.getTail());
116 } else if (d.getInjectionPoint().equals(TypeC.TYPE_A)) {
117
118 Assert.assertFalse(deps.containsKey(TypeC.TYPE_A));
119 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof ProviderClassSatisfaction);
120 Assert.assertEquals(ProviderA.class, ((ProviderClassSatisfaction) e.getTail().getLabel().getSatisfaction()).getProviderType());
121 deps.put(TypeC.TYPE_A, e.getTail());
122 } else if (d.getInjectionPoint().equals(TypeC.INTERFACE_B)) {
123
124 Assert.assertFalse(deps.containsKey(TypeC.INTERFACE_B));
125 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof ClassSatisfaction);
126 Assert.assertEquals(TypeB.class, e.getTail().getLabel().getSatisfaction().getErasedType());
127 deps.put(TypeC.INTERFACE_B, e.getTail());
128 } else if (d.getInjectionPoint().equals(TypeC.TYPE_B)) {
129
130 Assert.assertFalse(deps.containsKey(TypeC.TYPE_B));
131 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof ClassSatisfaction);
132 Assert.assertEquals(TypeB.class, e.getTail().getLabel().getSatisfaction().getErasedType());
133 deps.put(TypeC.TYPE_B, e.getTail());
134 } else {
135 Assert.fail();
136 }
137 }
138
139
140 Assert.assertTrue(deps.containsKey(TypeC.CONSTRUCTOR));
141 Assert.assertTrue(deps.containsKey(TypeC.TYPE_A));
142 Assert.assertTrue(deps.containsKey(TypeC.INTERFACE_A));
143 Assert.assertTrue(deps.containsKey(TypeC.TYPE_B));
144 Assert.assertTrue(deps.containsKey(TypeC.INTERFACE_B));
145
146
147 Assert.assertSame(deps.get(TypeC.INTERFACE_A), deps.get(TypeC.TYPE_A));
148 Assert.assertSame(deps.get(TypeC.INTERFACE_B), deps.get(TypeC.TYPE_B));
149 }
150
151 @Test
152 public void testTypeCInjectionWithBindings() throws Exception {
153
154
155
156 Desire rootDesire = Desires.create(null, TypeC.class, false);
157
158 TypeA a = new TypeA();
159 TypeB b = new TypeB();
160
161 BindingFunctionBuilder bindRules = new BindingFunctionBuilder(false);
162 bindRules.getRootContext().bind(Integer.class).withQualifier(ParameterA.class).to(10);
163 bindRules.getRootContext().bind(InterfaceA.class).withQualifier(RoleA.class).to(PrimeA.class);
164 bindRules.getRootContext().bind(InterfaceB.class).withQualifier(RoleD.class).to(PrimeB.class);
165 bindRules.getRootContext().bind(TypeA.class).to(a);
166 bindRules.getRootContext().bind(TypeB.class).to(b);
167
168 DefaultInjector r = new DefaultInjector(bindRules.build(RuleSet.EXPLICIT), DefaultDesireBindingFunction.create());
169
170 TypeC instance = r.getInstance(TypeC.class);
171 Assert.assertEquals(10, instance.getIntValue());
172 Assert.assertNotNull(instance.getInterfaceA());
173 Assert.assertTrue(instance.getInterfaceA() instanceof PrimeA);
174 Assert.assertSame(a, instance.getTypeA());
175 Assert.assertNotNull(instance.getInterfaceB());
176 Assert.assertTrue(instance.getInterfaceB() instanceof PrimeB);
177 Assert.assertSame(b, instance.getTypeB());
178
179
180 Assert.assertSame(instance, r.getInstance(TypeC.class));
181
182 DAGNode<Component, Dependency> resolvedRoot =
183 r.getSolver().getGraph().getOutgoingEdgeWithLabel(Dependency.hasInitialDesire(rootDesire)).getTail();
184 assertThat(resolvedRoot.getOutgoingEdges(),
185 hasSize(5));
186
187 Map<InjectionPoint, DAGNode<Component, Dependency>> deps = Maps.newHashMap();
188 for (DAGEdge<Component, Dependency> e: resolvedRoot.getOutgoingEdges()) {
189 ReflectionDesire d = (ReflectionDesire) e.getLabel().getInitialDesire();
190
191 if (d.getInjectionPoint().equals(TypeC.CONSTRUCTOR)) {
192
193 Assert.assertFalse(deps.containsKey(TypeC.CONSTRUCTOR));
194 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof InstanceSatisfaction);
195 Assert.assertEquals(10, ((InstanceSatisfaction) e.getTail().getLabel().getSatisfaction()).getInstance());
196 deps.put(TypeC.CONSTRUCTOR, e.getTail());
197 } else if (d.getInjectionPoint().equals(TypeC.INTERFACE_A)) {
198
199 Assert.assertFalse(deps.containsKey(TypeC.INTERFACE_A));
200 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof ClassSatisfaction);
201 Assert.assertEquals(PrimeA.class, e.getTail().getLabel().getSatisfaction().getErasedType());
202 deps.put(TypeC.INTERFACE_A, e.getTail());
203 } else if (d.getInjectionPoint().equals(TypeC.TYPE_A)) {
204
205 Assert.assertFalse(deps.containsKey(TypeC.TYPE_A));
206 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof InstanceSatisfaction);
207 Assert.assertSame(a, ((InstanceSatisfaction) e.getTail().getLabel().getSatisfaction()).getInstance());
208 deps.put(TypeC.TYPE_A, e.getTail());
209 } else if (d.getInjectionPoint().equals(TypeC.INTERFACE_B)) {
210
211 Assert.assertFalse(deps.containsKey(TypeC.INTERFACE_B));
212 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof ClassSatisfaction);
213 Assert.assertEquals(PrimeB.class, e.getTail().getLabel().getSatisfaction().getErasedType());
214 deps.put(TypeC.INTERFACE_B, e.getTail());
215 } else if (d.getInjectionPoint().equals(TypeC.TYPE_B)) {
216
217 Assert.assertFalse(deps.containsKey(TypeC.TYPE_B));
218 Assert.assertTrue(e.getTail().getLabel().getSatisfaction() instanceof InstanceSatisfaction);
219 Assert.assertSame(b, ((InstanceSatisfaction) e.getTail().getLabel().getSatisfaction()).getInstance());
220 deps.put(TypeC.TYPE_B, e.getTail());
221 } else {
222 Assert.fail();
223 }
224 }
225
226
227 Assert.assertTrue(deps.containsKey(TypeC.CONSTRUCTOR));
228 Assert.assertTrue(deps.containsKey(TypeC.TYPE_A));
229 Assert.assertTrue(deps.containsKey(TypeC.INTERFACE_A));
230 Assert.assertTrue(deps.containsKey(TypeC.TYPE_B));
231 Assert.assertTrue(deps.containsKey(TypeC.INTERFACE_B));
232 }
233
234 public static class PrimeA implements InterfaceA {
235
236 }
237
238 public static class PrimeB implements InterfaceB {
239
240 }
241 }