1 /* 2 * Copyright (C) 2022 The Dagger Authors. 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 dagger.internal.codegen; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import androidx.room.compiler.processing.XAnnotation; 22 import androidx.room.compiler.processing.XProcessingEnv; 23 import androidx.room.compiler.processing.XTypeElement; 24 import com.google.testing.compile.CompilationRule; 25 import com.squareup.javapoet.ClassName; 26 import dagger.Component; 27 import dagger.internal.codegen.javac.JavacPluginModule; 28 import dagger.internal.codegen.xprocessing.XAnnotations; 29 import javax.inject.Inject; 30 import javax.inject.Singleton; 31 import javax.lang.model.util.Elements; 32 import javax.lang.model.util.Types; 33 import org.junit.Before; 34 import org.junit.Rule; 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 import org.junit.runners.JUnit4; 38 39 @RunWith(JUnit4.class) 40 public class XAnnotationsToStableStringTest { 41 static final class Foo {} 42 43 enum MyEnum { 44 V1, 45 V2 46 } 47 48 @interface SingleValueWithCustomNameAnnotation { classValue()49 Class<?> classValue(); 50 } 51 52 @interface SingleValueWithDefaultAnnotation { value()53 Class<?> value() default Object.class; 54 } 55 56 @interface SingleValueAnnotation { value()57 Class<?> value(); 58 } 59 60 @interface MultiValueAnnotation { enumValue()61 MyEnum enumValue(); 62 classValue()63 Class<?> classValue(); 64 booleanValue()65 boolean booleanValue(); 66 byteValue()67 byte byteValue(); 68 charValue()69 char charValue(); 70 intValue()71 int intValue(); 72 longValue()73 long longValue(); 74 shortValue()75 short shortValue(); 76 floatValue()77 float floatValue(); 78 doubleValue()79 double doubleValue(); 80 stringValue()81 String stringValue(); 82 stringWithDefaultValue()83 String stringWithDefaultValue() default "Default value"; 84 stringWithMultipleArrayValue()85 String[] stringWithMultipleArrayValue(); 86 stringWithSingleArrayValue()87 String[] stringWithSingleArrayValue(); 88 singleValueAnnotations()89 SingleValueAnnotation[] singleValueAnnotations(); 90 } 91 92 @SingleValueAnnotation(value = Foo.class) 93 @SingleValueWithDefaultAnnotation 94 @SingleValueWithCustomNameAnnotation(classValue = Foo.class) 95 @MultiValueAnnotation( 96 // Note: the value orders are purposely randomized for this test 97 doubleValue = 13.2, 98 longValue = 7L, 99 stringWithSingleArrayValue = {"STRING_VALUE1"}, 100 byteValue = 3, 101 enumValue = MyEnum.V1, 102 charValue = 'c', 103 stringWithMultipleArrayValue = {"STRING_VALUE1", "STRING_VALUE2"}, 104 shortValue = 9, 105 classValue = Foo.class, 106 stringValue = "STRING_VALUE1", 107 booleanValue = false, 108 floatValue = 11.1f, 109 singleValueAnnotations = { 110 @SingleValueAnnotation(Object.class), 111 @SingleValueAnnotation(Foo.class), 112 @SingleValueAnnotation(String.class) 113 }, 114 intValue = 5) 115 interface Usage {} 116 117 @Rule public CompilationRule compilationRule = new CompilationRule(); 118 119 @Inject XProcessingEnv processingEnv; 120 121 private final String testName = getClass().getCanonicalName(); 122 123 @Before setUp()124 public void setUp() { 125 TestComponent.create(compilationRule.getElements(), compilationRule.getTypes()).inject(this); 126 } 127 128 @Test multiValueAnnotationTest()129 public void multiValueAnnotationTest() { 130 XTypeElement typeElement = processingEnv.requireTypeElement(Usage.class.getCanonicalName()); 131 XAnnotation annotation = typeElement.getAnnotation(ClassName.get(MultiValueAnnotation.class)); 132 assertThat(XAnnotations.toStableString(annotation)) 133 .isEqualTo( 134 String.format( 135 "@%1$s.MultiValueAnnotation(" 136 + "enumValue=V1, " 137 + "classValue=%1$s.Foo, " 138 + "booleanValue=false, " 139 + "byteValue=3, " 140 + "charValue='c', " 141 + "intValue=5, " 142 + "longValue=7, " 143 + "shortValue=9, " 144 + "floatValue=11.1, " 145 + "doubleValue=13.2, " 146 + "stringValue=\"STRING_VALUE1\", " 147 + "stringWithDefaultValue=\"Default value\", " 148 + "stringWithMultipleArrayValue={\"STRING_VALUE1\", \"STRING_VALUE2\"}, " 149 + "stringWithSingleArrayValue={\"STRING_VALUE1\"}, " 150 + "singleValueAnnotations={" 151 + "@%1$s.SingleValueAnnotation(java.lang.Object), " 152 + "@%1$s.SingleValueAnnotation(%1$s.Foo), " 153 + "@%1$s.SingleValueAnnotation(java.lang.String)" 154 + "})", 155 testName)); 156 } 157 158 @Test singleValueAnnotationTest()159 public void singleValueAnnotationTest() { 160 XTypeElement typeElement = processingEnv.requireTypeElement(Usage.class.getCanonicalName()); 161 XAnnotation annotation = typeElement.getAnnotation(ClassName.get(SingleValueAnnotation.class)); 162 assertThat(XAnnotations.toStableString(annotation)) 163 .isEqualTo(String.format("@%1$s.SingleValueAnnotation(%1$s.Foo)", testName)); 164 } 165 166 @Test singleValueWithDefaultAnnotationTest()167 public void singleValueWithDefaultAnnotationTest() { 168 XTypeElement typeElement = processingEnv.requireTypeElement(Usage.class.getCanonicalName()); 169 XAnnotation annotation = 170 typeElement.getAnnotation(ClassName.get(SingleValueWithDefaultAnnotation.class)); 171 assertThat(XAnnotations.toStableString(annotation)) 172 .isEqualTo( 173 String.format("@%1$s.SingleValueWithDefaultAnnotation(java.lang.Object)", testName)); 174 } 175 176 @Test singleValueWithCustomNameAnnotationTest()177 public void singleValueWithCustomNameAnnotationTest() { 178 XTypeElement typeElement = processingEnv.requireTypeElement(Usage.class.getCanonicalName()); 179 XAnnotation annotation = 180 typeElement.getAnnotation(ClassName.get(SingleValueWithCustomNameAnnotation.class)); 181 assertThat(XAnnotations.toStableString(annotation)) 182 .isEqualTo( 183 String.format( 184 "@%1$s.SingleValueWithCustomNameAnnotation(classValue=%1$s.Foo)", testName)); 185 } 186 187 @Singleton 188 @Component(modules = JavacPluginModule.class) 189 interface TestComponent { create(Elements elements, Types types)190 static TestComponent create(Elements elements, Types types) { 191 return DaggerXAnnotationsToStableStringTest_TestComponent.builder() 192 .javacPluginModule(new JavacPluginModule(elements, types)) 193 .build(); 194 } 195 inject(XAnnotationsToStableStringTest test)196 void inject(XAnnotationsToStableStringTest test); 197 } 198 } 199