1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht;
21
22 import com.google.common.collect.ArrayListMultimap;
23 import com.google.common.collect.HashMultimap;
24 import com.google.common.collect.ListMultimap;
25 import com.google.common.collect.SetMultimap;
26 import org.grouplens.grapht.BindingFunctionBuilder.RuleSet;
27 import org.grouplens.grapht.solver.BindRule;
28 import org.grouplens.grapht.solver.BindRules;
29 import org.grouplens.grapht.solver.RuleBasedBindingFunction;
30 import org.grouplens.grapht.reflect.Satisfactions;
31 import org.grouplens.grapht.context.ContextElements;
32 import org.grouplens.grapht.context.ContextMatcher;
33 import org.grouplens.grapht.context.ContextPattern;
34 import org.grouplens.grapht.reflect.Qualifiers;
35 import org.grouplens.grapht.reflect.internal.types.*;
36 import org.junit.Assert;
37 import org.junit.Ignore;
38 import org.junit.Test;
39
40 import javax.inject.Provider;
41 import java.io.InputStream;
42 import java.io.OutputStream;
43
44 import static org.junit.Assert.assertEquals;
45 import static org.junit.Assert.fail;
46
47 public class BindingFunctionBuilderTest {
48 @Test
49 public void testCachePolicy() throws Exception {
50 doCachePolicyTest(CachePolicy.MEMOIZE);
51 doCachePolicyTest(CachePolicy.NEW_INSTANCE);
52 doCachePolicyTest(CachePolicy.NO_PREFERENCE);
53 }
54
55 private void doCachePolicyTest(CachePolicy expectedPolicy) throws Exception {
56 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
57
58 if (expectedPolicy.equals(CachePolicy.MEMOIZE)) {
59 builder.getRootContext().bind(InterfaceA.class).shared().to(TypeA.class);
60 } else if (expectedPolicy.equals(CachePolicy.NEW_INSTANCE)) {
61 builder.getRootContext().bind(InterfaceA.class).unshared().to(TypeA.class);
62 } else {
63 builder.getRootContext().bind(InterfaceA.class).to(TypeA.class);
64 }
65
66
67 ListMultimap<ContextMatcher,BindRule> expected = ArrayListMultimap.create();
68 expected.put(ContextPattern.any(),
69 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeA.class), expectedPolicy, false));
70
71 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
72 }
73
74 @Test
75 public void testBindToType() throws Exception {
76
77
78 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
79
80 builder.getRootContext().bind(InterfaceA.class).to(TypeA.class);
81
82
83 ListMultimap<ContextMatcher,BindRule> expected = ArrayListMultimap.create();
84 expected.put(ContextPattern.any(),
85 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeA.class), CachePolicy.NO_PREFERENCE, false));
86
87 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
88 }
89
90 @Test
91 public void testBindToInstance() throws Exception {
92
93
94 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
95
96 TypeA a = new TypeA();
97 builder.getRootContext().bind(InterfaceA.class).to(a);
98
99
100 ListMultimap<ContextMatcher,BindRule> expected = ArrayListMultimap.create();
101 expected.put(ContextPattern.any(),
102 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.instance(a), CachePolicy.NO_PREFERENCE, true));
103
104 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
105 }
106
107 @Test
108 public void testBindToProviderType() throws Exception {
109
110
111 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
112
113 builder.getRootContext().bind(InterfaceA.class).toProvider(ProviderA.class);
114
115
116 ListMultimap<ContextMatcher,BindRule> expected = ArrayListMultimap.create();
117 expected.put(ContextPattern.any(),
118 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.providerType(ProviderA.class), CachePolicy.NO_PREFERENCE, true));
119
120 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
121 }
122
123 @Test
124 public void testBindToProviderInstance() throws Exception {
125
126
127 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
128
129 ProviderA pa = new ProviderA();
130 builder.getRootContext().bind(InterfaceA.class).toProvider(pa);
131
132
133 ListMultimap<ContextMatcher,BindRule> expected = ArrayListMultimap.create();
134 expected.put(ContextPattern.any(),
135 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.providerInstance(pa), CachePolicy.NO_PREFERENCE, true));
136
137 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
138 }
139
140 @Test
141 public void testBindToSatisfaction() throws Exception {
142
143
144 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
145
146 builder.getRootContext().bind(InterfaceA.class).toSatisfaction(Satisfactions.type(TypeA.class));
147
148
149 ListMultimap<ContextMatcher,BindRule> expected = ArrayListMultimap.create();
150 expected.put(ContextPattern.any(),
151 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeA.class), CachePolicy.NO_PREFERENCE, true));
152
153 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
154 }
155
156 @SuppressWarnings("unchecked")
157 @Test
158 public void testBindToWrongProvider() throws Exception {
159
160
161 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
162 try {
163 builder.getRootContext()
164 .bind((Class) InterfaceA.class)
165 .toProvider(ProviderC.class);
166 fail("binding to incompatible provider should throw exception");
167 } catch (InvalidBindingException e) {
168
169 }
170 }
171
172 @SuppressWarnings("unchecked")
173 @Test
174 public void testBindToBadProvider() throws Exception {
175
176 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
177 try {
178 builder.getRootContext()
179 .bind((Class) InputStream.class)
180 .toProvider(new InstanceProvider("foo"));
181 fail("binding to bad provider should throw exception");
182 } catch (InvalidBindingException e) {
183
184 }
185 }
186
187 @Test
188 public void testInjectorContextSpecificBindRules() throws Exception {
189
190
191 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
192
193 builder.getRootContext().bind(InterfaceA.class).to(TypeA.class);
194 builder.getRootContext().in(TypeC.class).bind(InterfaceA.class).to(TypeB.class);
195 builder.getRootContext().in(RoleD.class, TypeC.class).bind(InterfaceB.class).to(TypeB.class);
196
197
198 ListMultimap<ContextMatcher, BindRule> expected = ArrayListMultimap.create();
199 expected.put(ContextPattern.any(),
200 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeA.class), CachePolicy.NO_PREFERENCE, false));
201
202 expected.put(ContextPattern.subsequence(ContextElements.matchType(TypeC.class, Qualifiers.matchDefault())),
203 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeB.class), CachePolicy.NO_PREFERENCE, false));
204 expected.put(ContextPattern.subsequence(ContextElements.matchType(TypeC.class, Qualifiers.match(RoleD.class))),
205 BindRules.toSatisfaction(InterfaceB.class, Qualifiers.matchDefault(), Satisfactions.type(TypeB.class), CachePolicy.NO_PREFERENCE, false));
206
207 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
208 }
209
210 @Test
211 public void testFinalBindRule() throws Exception {
212
213 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
214
215 builder.getRootContext().bind(InterfaceA.class).to(TypeA.class, false);
216
217
218 ListMultimap<ContextMatcher, BindRule> expected = ArrayListMultimap.create();
219 expected.put(ContextPattern.any(),
220 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeA.class), CachePolicy.NO_PREFERENCE, true));
221
222 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
223 }
224
225 @Test
226 public void testAnnotatedBindings() throws Exception {
227
228 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
229
230 builder.getRootContext().bind(InterfaceA.class).withQualifier(RoleD.class).to(TypeA.class);
231
232
233 ListMultimap<ContextMatcher, BindRule> expected = ArrayListMultimap.create();
234 expected.put(ContextPattern.any(),
235 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.match(RoleD.class), Satisfactions.type(TypeA.class), CachePolicy.NO_PREFERENCE, false));
236
237 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
238 }
239
240 @Test
241 public void testAnyQualifierBindings() throws Exception {
242
243 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
244
245 builder.getRootContext().bind(InterfaceA.class).withAnyQualifier().to(TypeA.class);
246
247
248 ListMultimap<ContextMatcher, BindRule> expected = ArrayListMultimap.create();
249 expected.put(ContextPattern.any(),
250 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchAny(), Satisfactions.type(TypeA.class), CachePolicy.NO_PREFERENCE, false));
251
252 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
253 }
254
255 @Test
256 public void testNamedBindings() throws Exception {
257
258 BindingFunctionBuilder builder = new BindingFunctionBuilder(false);
259
260 builder.getRootContext().bind(String.class).withQualifier(Names.named("test1")).to("hello world");
261
262
263 ListMultimap<ContextMatcher, BindRule> expected = ArrayListMultimap.create();
264 expected.put(ContextPattern.any(),
265 BindRules.toSatisfaction(String.class, Qualifiers.match(Names.named("test1")), Satisfactions.instance("hello world"), CachePolicy.NO_PREFERENCE, true));
266
267 assertEqualBindings(expected, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
268 }
269
270 @Test
271 public void testBindRuleGeneration() throws Exception {
272
273 BindingFunctionBuilder builder = new BindingFunctionBuilder(true);
274
275 builder.getRootContext().bind(TypeA.class).to(TypeBp.class);
276
277
278 ListMultimap<ContextMatcher, BindRule> explicit = ArrayListMultimap.create();
279 explicit.put(ContextPattern.any(),
280 BindRules.toSatisfaction(TypeA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
281 ListMultimap<ContextMatcher, BindRule> superTypes = ArrayListMultimap.create();
282 superTypes.put(ContextPattern.any(),
283 BindRules.toSatisfaction(InterfaceA.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
284 ListMultimap<ContextMatcher, BindRule> interTypes = ArrayListMultimap.create();
285 ContextMatcher m = ContextPattern.any();
286 interTypes.put(m, BindRules.toSatisfaction(TypeB.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
287 interTypes.put(m, BindRules.toSatisfaction(TypeBp.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
288
289 assertEqualBindings(explicit, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
290 assertEqualBindings(superTypes, ((RuleBasedBindingFunction) builder.build(RuleSet.SUPER_TYPES)).getRules());
291 assertEqualBindings(interTypes, ((RuleBasedBindingFunction) builder.build(RuleSet.INTERMEDIATE_TYPES)).getRules());
292 }
293
294 @Test
295 public void testBindRuleGenerationExcludesDefault() throws Exception {
296
297
298 BindingFunctionBuilder builder = new BindingFunctionBuilder(true);
299 builder.addDefaultExclusion(TypeA.class);
300
301 builder.getRootContext().bind(TypeB.class).to(TypeBp.class);
302
303
304 ListMultimap<ContextMatcher, BindRule> explicit = ArrayListMultimap.create();
305 explicit.put(ContextPattern.any(),
306 BindRules.toSatisfaction(TypeB.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
307 ListMultimap<ContextMatcher, BindRule> interTypes = ArrayListMultimap.create();
308 interTypes.put(ContextPattern.any(),
309 BindRules.toSatisfaction(TypeBp.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
310 ListMultimap<ContextMatcher, BindRule> superTypes = ArrayListMultimap.create();
311 superTypes.put(ContextPattern.any(),
312 BindRules.toSatisfaction(InterfaceB.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
313
314 assertEqualBindings(explicit, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
315 assertEqualBindings(superTypes, ((RuleBasedBindingFunction) builder.build(RuleSet.SUPER_TYPES)).getRules());
316 assertEqualBindings(interTypes, ((RuleBasedBindingFunction) builder.build(RuleSet.INTERMEDIATE_TYPES)).getRules());
317 }
318
319 @Test
320 public void testBindRuleGenerationWithBindingExclude() throws Exception {
321
322
323 BindingFunctionBuilder builder = new BindingFunctionBuilder(true);
324
325 builder.getRootContext().bind(TypeB.class).exclude(TypeA.class).to(TypeBp.class);
326
327
328 ListMultimap<ContextMatcher, BindRule> explicit = ArrayListMultimap.create();
329 explicit.put(ContextPattern.any(),
330 BindRules.toSatisfaction(TypeB.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
331 ListMultimap<ContextMatcher, BindRule> interTypes = ArrayListMultimap.create();
332 interTypes.put(ContextPattern.any(),
333 BindRules.toSatisfaction(TypeBp.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
334 ListMultimap<ContextMatcher, BindRule> superTypes = ArrayListMultimap.create();
335 superTypes.put(ContextPattern.any(),
336 BindRules.toSatisfaction(InterfaceB.class, Qualifiers.matchDefault(), Satisfactions.type(TypeBp.class), CachePolicy.NO_PREFERENCE, false));
337
338 assertEqualBindings(explicit, ((RuleBasedBindingFunction) builder.build(RuleSet.EXPLICIT)).getRules());
339 assertEqualBindings(superTypes, ((RuleBasedBindingFunction) builder.build(RuleSet.SUPER_TYPES)).getRules());
340 assertEqualBindings(interTypes, ((RuleBasedBindingFunction) builder.build(RuleSet.INTERMEDIATE_TYPES)).getRules());
341 }
342
343 @SuppressWarnings("unchecked")
344 @Test
345 public void testRejectInvalidBinding() {
346 BindingFunctionBuilder builder = new BindingFunctionBuilder(true);
347
348 try {
349 builder.getRootContext().bind((Class) OutputStream.class).to(String.class);
350 fail("binding should have thrown an exception");
351 } catch (InvalidBindingException e) {
352
353 }
354 }
355
356 @SuppressWarnings("unchecked")
357 @Test
358 public void testRejectInvalidInstanceBinding() {
359 BindingFunctionBuilder builder = new BindingFunctionBuilder(true);
360
361 try {
362 builder.getRootContext().bind((Class) OutputStream.class).to("wombat");
363 fail("binding should have thrown an exception");
364 } catch (InvalidBindingException e) {
365
366 }
367 }
368
369 private void assertEqualBindings(ListMultimap<ContextMatcher, BindRule> expected, ListMultimap<ContextMatcher, BindRule> actual) {
370
371
372 Assert.assertEquals(expected.size(), actual.size());
373 SetMultimap eset = HashMultimap.create(expected);
374 SetMultimap aset = HashMultimap.create(actual);
375 assertEquals(eset, aset);
376 }
377
378
379 public static class TypeBp extends TypeB { }
380
381 public static class InstanceProvider<T> implements Provider<T> {
382 private final T instance;
383
384 public InstanceProvider(T obj) {
385 instance = obj;
386 }
387
388 @Override
389 public T get() {
390 return instance;
391 }
392 }
393 }