1 /** 2 * Copyright (C) 2008 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 static java.lang.annotation.RetentionPolicy.RUNTIME; 20 21 import com.google.inject.AbstractModule; 22 import com.google.inject.BindingAnnotation; 23 import com.google.inject.Guice; 24 import com.google.inject.Injector; 25 import com.google.inject.Key; 26 import com.google.inject.Provider; 27 import com.google.inject.Provides; 28 import com.google.inject.TypeLiteral; 29 import com.google.inject.internal.ProviderMethod; 30 import com.google.inject.internal.util.StackTraceElements; 31 import com.google.inject.name.Names; 32 import com.google.inject.spi.DefaultBindingTargetVisitor; 33 import com.google.inject.spi.ProviderInstanceBinding; 34 35 import junit.framework.TestCase; 36 37 import java.lang.annotation.ElementType; 38 import java.lang.annotation.Retention; 39 import java.lang.annotation.Target; 40 import java.lang.reflect.Member; 41 42 /** 43 * Tests for {@link ShortNameFactory}. 44 * 45 * @author phopkins@gmail.com (Pete Hopkins) 46 */ 47 public class ShortNameFactoryTest extends TestCase { 48 // Helper objects are up here because their line numbers are tested below. 49 private static class Obj { 50 @Annotated 51 public String field; Obj()52 Obj() {} method(String parameter)53 void method(String parameter) {} 54 } 55 56 private static class ToStringObj { 57 @Override toString()58 public String toString() { 59 return "I'm a ToStringObj"; 60 } 61 } 62 63 @Retention(RUNTIME) 64 @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) 65 @BindingAnnotation 66 private @interface Annotated {} 67 68 private NameFactory nameFactory; 69 70 @Override setUp()71 protected void setUp() throws Exception { 72 super.setUp(); 73 74 nameFactory = new ShortNameFactory(); 75 } 76 testGetMemberName_field()77 public void testGetMemberName_field() throws Exception { 78 Member field = Obj.class.getDeclaredField("field"); 79 assertEquals("field", nameFactory.getMemberName(field)); 80 } 81 testGetMemberName_method()82 public void testGetMemberName_method() throws Exception { 83 Member method = Obj.class.getDeclaredMethod("method", String.class); 84 assertEquals("#method(...)", nameFactory.getMemberName(method)); 85 } 86 testGetMemberName_constructor()87 public void testGetMemberName_constructor() throws Exception { 88 Member constructor = Obj.class.getDeclaredConstructor(); 89 assertEquals("<init>", nameFactory.getMemberName(constructor)); 90 } 91 testGetAnnotationName_annotationType()92 public void testGetAnnotationName_annotationType() throws Exception { 93 Key<?> key = Key.get(String.class, Annotated.class); 94 assertEquals("@Annotated", nameFactory.getAnnotationName(key)); 95 } 96 testGetAnnotationName_annotationInstance()97 public void testGetAnnotationName_annotationInstance() throws Exception { 98 Key<?> key = Key.get(String.class, 99 Obj.class.getDeclaredField("field").getDeclaredAnnotations()[0]); 100 assertEquals("@Annotated", nameFactory.getAnnotationName(key)); 101 } 102 testGetAnnotationName_annotationInstanceWithParameters()103 public void testGetAnnotationName_annotationInstanceWithParameters() throws Exception { 104 Key<?> key = Key.get(String.class, Names.named("name")); 105 assertEquals("@Named(value=name)", nameFactory.getAnnotationName(key)); 106 } 107 testGetClassName_key()108 public void testGetClassName_key() throws Exception { 109 Key<?> key = Key.get(Obj.class); 110 assertEquals("Class name should not have the package", 111 "ShortNameFactoryTest$Obj", nameFactory.getClassName(key)); 112 } 113 testGetClassName_keyWithTypeParameters()114 public void testGetClassName_keyWithTypeParameters() throws Exception { 115 Key<?> key = Key.get(new TypeLiteral<Provider<String>>() {}); 116 assertEquals("Class name and type values should not have packages", 117 "Provider<String>", nameFactory.getClassName(key)); 118 } 119 120 /** 121 * Tests the case where a provider method is the source of the 122 * @throws Exception 123 */ testGetSourceName_method()124 public void testGetSourceName_method() throws Exception { 125 Member method = Obj.class.getDeclaredMethod("method", String.class); 126 assertEquals("Method should be identified by its file name and line number", 127 "ShortNameFactoryTest.java:53", nameFactory.getSourceName(method)); 128 } 129 testGetSourceName_stackTraceElement()130 public void testGetSourceName_stackTraceElement() throws Exception { 131 StackTraceElement element = 132 (StackTraceElement) StackTraceElements.forMember(Obj.class.getField("field")); 133 assertEquals("Stack trace element should be identified by its file name and line number", 134 "ShortNameFactoryTest.java:52", nameFactory.getSourceName(element)); 135 } 136 testGetInstanceName_defaultToString()137 public void testGetInstanceName_defaultToString() throws Exception { 138 assertEquals("Should use class name instead of Object#toString()", 139 "ShortNameFactoryTest$Obj", nameFactory.getInstanceName(new Obj())); 140 } 141 testGetInstanceName_customToString()142 public void testGetInstanceName_customToString() throws Exception { 143 assertEquals("Should use class's toString() method since it's defined", 144 "I'm a ToStringObj", nameFactory.getInstanceName(new ToStringObj())); 145 } 146 testGetInstanceName_string()147 public void testGetInstanceName_string() throws Exception { 148 assertEquals("String should have quotes to evoke a string literal", 149 "\"My String Instance\"", nameFactory.getInstanceName("My String Instance")); 150 } 151 testGetInstanceName_providerMethod()152 public void testGetInstanceName_providerMethod() throws Exception { 153 final ProviderMethod<?>[] methodHolder = new ProviderMethod[1]; 154 155 Injector injector = Guice.createInjector(new ProvidingModule()); 156 injector.getBinding(Integer.class).acceptTargetVisitor( 157 new DefaultBindingTargetVisitor<Object, Void>() { 158 @SuppressWarnings("unchecked") @Override 159 public Void visit(ProviderInstanceBinding<?> binding) { 160 methodHolder[0] = (ProviderMethod) binding.getUserSuppliedProvider(); 161 return null; 162 } 163 }); 164 165 assertEquals("Method provider should pretty print as the method signature", 166 "#provideInteger(String)", nameFactory.getInstanceName(methodHolder[0])); 167 } 168 169 private static class ProvidingModule extends AbstractModule { 170 @Override configure()171 protected void configure() {} 172 173 @Provides provideInteger(String string)174 public Integer provideInteger(String string) { 175 return Integer.valueOf(string); 176 } 177 } 178 } 179