• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.google.inject.spi;
2 
3 import static com.google.inject.internal.InternalFlags.getIncludeStackTraceOption;
4 import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 
6 import com.google.inject.AbstractModule;
7 import com.google.inject.Binder;
8 import com.google.inject.Binding;
9 import com.google.inject.BindingAnnotation;
10 import com.google.inject.Module;
11 import java.lang.annotation.Annotation;
12 import java.lang.annotation.ElementType;
13 import java.lang.annotation.Retention;
14 import java.lang.annotation.Target;
15 import java.util.List;
16 import junit.framework.TestCase;
17 
18 /** Tests for {@link ElementSource}. */
19 public class ElementSourceTest extends TestCase {
20 
21   private static final StackTraceElement BINDER_INSTALL =
22       new StackTraceElement(
23           "com.google.inject.spi.Elements$RecordingBinder",
24           "install",
25           "Unknown Source",
26           234 /* line number*/);
27 
testCallStackSize()28   public void testCallStackSize() {
29     ModuleSource moduleSource = createModuleSource();
30     StackTraceElement[] bindingCallStack = new StackTraceElement[3];
31     bindingCallStack[0] =
32         new StackTraceElement(
33             "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 200);
34     bindingCallStack[1] =
35         new StackTraceElement(
36             "com.google.inject.spi.Elements$RecordingBinder", "bind", "Unknown Source", 100);
37     bindingCallStack[2] =
38         new StackTraceElement(
39             "com.google.inject.spi.moduleSourceTest$C", "configure", "Unknown Source", 100);
40     ElementSource elementSource =
41         new ElementSource(
42             null /* No original element source */,
43             "" /* Don't care */,
44             moduleSource,
45             bindingCallStack);
46     assertEquals(10 /* call stack size */, elementSource.getStackTrace().length);
47   }
48 
testGetCallStack_IntegrationTest()49   public void testGetCallStack_IntegrationTest() throws Exception {
50     List<Element> elements = Elements.getElements(new A());
51     for (Element element : elements) {
52       if (element instanceof Binding) {
53         Binding<?> binding = (Binding<?>) element;
54         Class<? extends Annotation> annotationType = binding.getKey().getAnnotationType();
55         if (annotationType != null && annotationType.equals(SampleAnnotation.class)) {
56           ElementSource elementSource = (ElementSource) binding.getSource();
57           List<String> moduleClassNames = elementSource.getModuleClassNames();
58           // Check module class names
59           // Module C
60           assertEquals("com.google.inject.spi.ElementSourceTest$C", moduleClassNames.get(0));
61           // Module B
62           assertEquals("com.google.inject.spi.ElementSourceTest$B", moduleClassNames.get(1));
63           // Module A
64           assertEquals("com.google.inject.spi.ElementSourceTest$A", moduleClassNames.get(2));
65           StackTraceElement[] callStack = elementSource.getStackTrace();
66           switch (getIncludeStackTraceOption()) {
67             case OFF:
68               // Check declaring source
69               StackTraceElement stackTraceElement =
70                   (StackTraceElement) elementSource.getDeclaringSource();
71               assertEquals(
72                   new StackTraceElement(
73                       "com.google.inject.spi.ElementSourceTest$C", "configure", null, -1),
74                   stackTraceElement);
75               // Check call stack
76               assertEquals(0, callStack.length);
77               return;
78             case ONLY_FOR_DECLARING_SOURCE:
79               // Check call stack
80               assertEquals(0, callStack.length);
81               return;
82             case COMPLETE:
83               // Check call stack
84               int skippedCallStackSize = new Throwable().getStackTrace().length - 1;
85               assertEquals(skippedCallStackSize + 15, elementSource.getStackTrace().length);
86               assertEquals(
87                   "com.google.inject.spi.Elements$RecordingBinder", callStack[0].getClassName());
88               assertEquals(
89                   "com.google.inject.spi.Elements$RecordingBinder", callStack[1].getClassName());
90               assertEquals("com.google.inject.AbstractModule", callStack[2].getClassName());
91               // Module C
92               assertEquals(
93                   "com.google.inject.spi.ElementSourceTest$C", callStack[3].getClassName());
94               assertEquals("configure", callStack[3].getMethodName());
95               assertEquals("Unknown Source", callStack[3].getFileName());
96               assertEquals("com.google.inject.AbstractModule", callStack[4].getClassName());
97               assertEquals(
98                   "com.google.inject.spi.Elements$RecordingBinder", callStack[5].getClassName());
99               // Module B
100               assertEquals(
101                   "com.google.inject.spi.ElementSourceTest$B", callStack[6].getClassName());
102               assertEquals(
103                   "com.google.inject.spi.Elements$RecordingBinder", callStack[7].getClassName());
104               // Module A
105               assertEquals("com.google.inject.AbstractModule", callStack[8].getClassName());
106               assertEquals(
107                   "com.google.inject.spi.ElementSourceTest$A", callStack[9].getClassName());
108               assertEquals("com.google.inject.AbstractModule", callStack[10].getClassName());
109               assertEquals(
110                   "com.google.inject.spi.Elements$RecordingBinder", callStack[11].getClassName());
111               assertEquals("com.google.inject.spi.Elements", callStack[12].getClassName());
112               assertEquals("com.google.inject.spi.Elements", callStack[13].getClassName());
113               assertEquals("com.google.inject.spi.ElementSourceTest", callStack[14].getClassName());
114               // Check modules index
115               List<Integer> indexes = elementSource.getModuleConfigurePositionsInStackTrace();
116               assertEquals(4, (int) indexes.get(0));
117               assertEquals(6, (int) indexes.get(1));
118               assertEquals(10, (int) indexes.get(2));
119               return;
120           }
121         }
122       }
123     }
124     fail("The test should not reach this line.");
125   }
126 
createModuleSource()127   private ModuleSource createModuleSource() {
128     // First module
129     StackTraceElement[] partialCallStack = new StackTraceElement[1];
130     partialCallStack[0] = BINDER_INSTALL;
131     ModuleSource moduleSource = new ModuleSource(new A(), partialCallStack);
132     // Second module
133     partialCallStack = new StackTraceElement[2];
134     partialCallStack[0] = BINDER_INSTALL;
135     partialCallStack[1] =
136         new StackTraceElement(
137             "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100);
138     moduleSource = moduleSource.createChild(new B(), partialCallStack);
139     // Third module
140     partialCallStack = new StackTraceElement[4];
141     partialCallStack[0] = BINDER_INSTALL;
142     partialCallStack[1] = new StackTraceElement("class1", "method1", "Class1.java", 1);
143     partialCallStack[2] = new StackTraceElement("class2", "method2", "Class2.java", 2);
144     partialCallStack[3] =
145         new StackTraceElement(
146             "com.google.inject.spi.moduleSourceTest$B", "configure", "Unknown Source", 200);
147     return moduleSource.createChild(new C(), partialCallStack);
148   }
149 
150   private static class A extends AbstractModule {
151     @Override
configure()152     public void configure() {
153       install(new B());
154     }
155   }
156 
157   private static class B implements Module {
158     @Override
configure(Binder binder)159     public void configure(Binder binder) {
160       binder.install(new C());
161     }
162   }
163 
164   @Retention(RUNTIME)
165   @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
166   @BindingAnnotation
167   @interface SampleAnnotation {}
168 
169   private static class C extends AbstractModule {
170     @Override
configure()171     public void configure() {
172       bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("the value");
173     }
174   }
175 }
176