1 /**
2  * Copyright (C) 2011 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject.grapher;
18 
19 import com.google.common.collect.ImmutableList;
20 import com.google.common.collect.ImmutableSet;
21 import com.google.common.collect.Sets;
22 import com.google.inject.AbstractModule;
23 import com.google.inject.BindingAnnotation;
24 import com.google.inject.Guice;
25 import com.google.inject.Inject;
26 import com.google.inject.Key;
27 import com.google.inject.Provider;
28 import com.google.inject.spi.InjectionPoint;
29 
30 import junit.framework.TestCase;
31 
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.lang.reflect.Member;
35 import java.util.Set;
36 
37 /**
38  * Test cases for {@link AbstractInjectorGrapher}. This indirectly tests most classes in this
39  * package.
40  *
41  * @author bojand@google.com (Bojan Djordjevic)
42  */
43 
44 public class AbstractInjectorGrapherTest extends TestCase {
45   private static final String TEST_STRING = "test";
46 
47   private static class FakeGrapher extends AbstractInjectorGrapher {
48     final Set<Node> nodes = Sets.newHashSet();
49     final Set<Edge> edges = Sets.newHashSet();
50 
reset()51     @Override protected void reset() {
52       nodes.clear();
53       edges.clear();
54     }
55 
newInterfaceNode(InterfaceNode node)56     @Override protected void newInterfaceNode(InterfaceNode node) {
57       assertFalse(nodes.contains(node));
58       nodes.add(node);
59     }
60 
newImplementationNode(ImplementationNode node)61     @Override protected void newImplementationNode(ImplementationNode node) {
62       assertFalse(nodes.contains(node));
63       nodes.add(node);
64     }
65 
newInstanceNode(InstanceNode node)66     @Override protected void newInstanceNode(InstanceNode node) {
67       assertFalse(nodes.contains(node));
68       nodes.add(node);
69     }
70 
newDependencyEdge(DependencyEdge edge)71     @Override protected void newDependencyEdge(DependencyEdge edge) {
72       assertFalse(edges.contains(edge));
73       edges.add(edge);
74     }
75 
newBindingEdge(BindingEdge edge)76     @Override protected void newBindingEdge(BindingEdge edge) {
77       assertFalse(edges.contains(edge));
78       edges.add(edge);
79     }
80 
postProcess()81     @Override protected void postProcess() {}
82   }
83 
84   private static final class Wrapper<T> {
85     T value;
86   }
87 
88   @BindingAnnotation
89   @Retention(RetentionPolicy.RUNTIME)
90   private static @interface Ann {}
91   private static interface IA {}
92   private static class A implements IA {
A(String str)93     @Inject public A(String str) {}
94   }
95   private static class A2 implements IA {
A2(Provider<String> strProvider)96     @Inject public A2(Provider<String> strProvider) {}
97   }
98 
99   private Node aNode;
100   private Node a2Node;
101   private Node iaNode;
102   private Node iaAnnNode;
103   private Node stringNode;
104   private Node stringInstanceNode;
105 
106   private FakeGrapher grapher;
107 
setUp()108   @Override protected void setUp() throws Exception {
109     super.setUp();
110     grapher = new FakeGrapher();
111     Node.ignoreSourceInComparisons = true;
112     aNode = new ImplementationNode(NodeId.newTypeId(Key.get(A.class)), null,
113         ImmutableList.<Member>of(A.class.getConstructor(String.class)));
114     a2Node = new ImplementationNode(NodeId.newTypeId(Key.get(A2.class)), null,
115         ImmutableList.<Member>of(A2.class.getConstructor(Provider.class)));
116     iaNode = new InterfaceNode(NodeId.newTypeId(Key.get(IA.class)), null);
117     iaAnnNode = new InterfaceNode(NodeId.newTypeId(Key.get(IA.class, Ann.class)), null);
118     stringNode = new InterfaceNode(NodeId.newTypeId(Key.get(String.class)), null);
119     stringInstanceNode = new InstanceNode(NodeId.newInstanceId(Key.get(String.class)), null,
120         TEST_STRING, ImmutableList.<Member>of());
121   }
122 
testLinkedAndInstanceBindings()123   public void testLinkedAndInstanceBindings() throws Exception {
124     grapher.graph(Guice.createInjector(new AbstractModule() {
125         @Override protected void configure() {
126           bind(IA.class).to(A.class);
127           bind(IA.class).annotatedWith(Ann.class).to(A.class);
128           bind(String.class).toInstance(TEST_STRING);
129         }
130     }));
131 
132     Set<Node> expectedNodes =
133         ImmutableSet.<Node>of(iaNode, iaAnnNode, aNode, stringNode, stringInstanceNode);
134     Set<Edge> expectedEdges = ImmutableSet.<Edge>of(
135         new BindingEdge(iaNode.getId(), aNode.getId(), BindingEdge.Type.NORMAL),
136         new BindingEdge(iaAnnNode.getId(), aNode.getId(), BindingEdge.Type.NORMAL),
137         new BindingEdge(stringNode.getId(), stringInstanceNode.getId(), BindingEdge.Type.NORMAL),
138         new DependencyEdge(aNode.getId(), stringNode.getId(),
139             InjectionPoint.forConstructor(A.class.getConstructor(String.class))));
140     assertEquals(expectedNodes, grapher.nodes);
141     assertEquals(expectedEdges, grapher.edges);
142   }
143 
testProviderBindings()144   public void testProviderBindings() throws Exception {
145     final Wrapper<Provider<A2>> wrapper = new Wrapper<Provider<A2>>();
146     grapher.graph(Guice.createInjector(new AbstractModule() {
147         @Override protected void configure() {
148           wrapper.value = getProvider(A2.class);
149           bind(IA.class).toProvider(wrapper.value);
150           bind(A2.class);
151           bind(String.class).toInstance(TEST_STRING);
152         }
153     }));
154 
155     Node a2ProviderNode = new InstanceNode(NodeId.newInstanceId(Key.get(IA.class)), null,
156         wrapper.value, ImmutableList.<Member>of());
157     Set<Node> expectedNodes =
158         ImmutableSet.<Node>of(iaNode, stringNode, a2Node, stringInstanceNode, a2ProviderNode);
159     Set<Edge> expectedEdges = ImmutableSet.<Edge>of(
160         new BindingEdge(stringNode.getId(), stringInstanceNode.getId(), BindingEdge.Type.NORMAL),
161         new BindingEdge(iaNode.getId(), a2ProviderNode.getId(), BindingEdge.Type.PROVIDER),
162         new DependencyEdge(a2Node.getId(), stringNode.getId(),
163             InjectionPoint.forConstructor(A2.class.getConstructor(Provider.class))),
164         new DependencyEdge(a2ProviderNode.getId(), a2Node.getId(), null));
165     assertEquals("wrong nodes", expectedNodes, grapher.nodes);
166     assertEquals("wrong edges", expectedEdges, grapher.edges);
167   }
168 
testGraphWithGivenRoot()169   public void testGraphWithGivenRoot() throws Exception {
170     grapher.graph(Guice.createInjector(new AbstractModule() {
171         @Override protected void configure() {
172           bind(IA.class).to(A.class);
173           bind(IA.class).annotatedWith(Ann.class).to(A.class);
174           bind(String.class).toInstance(TEST_STRING);
175         }
176     }), ImmutableSet.<Key<?>>of(Key.get(String.class)));
177 
178     Set<Node> expectedNodes = ImmutableSet.<Node>of(stringNode, stringInstanceNode);
179     Set<Edge> expectedEdges = ImmutableSet.<Edge>of(
180         new BindingEdge(stringNode.getId(), stringInstanceNode.getId(), BindingEdge.Type.NORMAL));
181     assertEquals(expectedNodes, grapher.nodes);
182     assertEquals(expectedEdges, grapher.edges);
183   }
184 }
185