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