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