• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 dagger.internal.codegen.DaggerModuleMethodSubject.Factory.assertThatMethodInUnannotatedClass;
20 import static dagger.internal.codegen.DaggerModuleMethodSubject.Factory.assertThatModuleMethod;
21 import static java.lang.annotation.RetentionPolicy.RUNTIME;
22 
23 import com.google.common.collect.ImmutableList;
24 import dagger.Module;
25 import dagger.multibindings.IntKey;
26 import dagger.multibindings.LongKey;
27 import dagger.producers.ProducerModule;
28 import java.lang.annotation.Annotation;
29 import java.lang.annotation.Retention;
30 import java.util.Collection;
31 import javax.inject.Qualifier;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.junit.runners.Parameterized;
35 import org.junit.runners.Parameterized.Parameters;
36 
37 @RunWith(Parameterized.class)
38 public class BindsMethodValidationTest {
39   @Parameters
data()40   public static Collection<Object[]> data() {
41     return ImmutableList.copyOf(new Object[][] {{Module.class}, {ProducerModule.class}});
42   }
43 
44   private final String moduleDeclaration;
45 
BindsMethodValidationTest(Class<? extends Annotation> moduleAnnotation)46   public BindsMethodValidationTest(Class<? extends Annotation> moduleAnnotation) {
47     moduleDeclaration = "@" + moduleAnnotation.getCanonicalName() + " abstract class %s { %s }";
48   }
49 
50   @Test
nonAbstract()51   public void nonAbstract() {
52     assertThatMethod("@Binds Object concrete(String impl) { return null; }")
53         .hasError("must be abstract");
54   }
55 
56   @Test
notAssignable()57   public void notAssignable() {
58     assertThatMethod("@Binds abstract String notAssignable(Object impl);").hasError("assignable");
59   }
60 
61   @Test
moreThanOneParameter()62   public void moreThanOneParameter() {
63     assertThatMethod("@Binds abstract Object tooManyParameters(String s1, String s2);")
64         .hasError("one parameter");
65   }
66 
67   @Test
typeParameters()68   public void typeParameters() {
69     assertThatMethod("@Binds abstract <S, T extends S> S generic(T t);")
70         .hasError("type parameters");
71   }
72 
73   @Test
notInModule()74   public void notInModule() {
75     assertThatMethodInUnannotatedClass("@Binds abstract Object bindObject(String s);")
76         .hasError("within a @Module or @ProducerModule");
77   }
78 
79   @Test
throwsException()80   public void throwsException() {
81     assertThatMethod("@Binds abstract Object throwsException(String s1) throws RuntimeException;")
82         .hasError("may not throw");
83   }
84 
85   @Test
returnsVoid()86   public void returnsVoid() {
87     assertThatMethod("@Binds abstract void returnsVoid(Object impl);").hasError("void");
88   }
89 
90   @Test
tooManyQualifiersOnMethod()91   public void tooManyQualifiersOnMethod() {
92     assertThatMethod(
93             "@Binds @Qualifier1 @Qualifier2 abstract String tooManyQualifiers(String impl);")
94         .importing(Qualifier1.class, Qualifier2.class)
95         .hasError("more than one @Qualifier");
96   }
97 
98   @Test
tooManyQualifiersOnParameter()99   public void tooManyQualifiersOnParameter() {
100     assertThatMethod(
101             "@Binds abstract String tooManyQualifiers(@Qualifier1 @Qualifier2 String impl);")
102         .importing(Qualifier1.class, Qualifier2.class)
103         .hasError("more than one @Qualifier");
104   }
105 
106   @Test
noParameters()107   public void noParameters() {
108     assertThatMethod("@Binds abstract Object noParameters();").hasError("one parameter");
109   }
110 
111   @Test
setElementsNotAssignable()112   public void setElementsNotAssignable() {
113     assertThatMethod(
114             "@Binds @ElementsIntoSet abstract Set<String> bindSetOfIntegers(Set<Integer> ints);")
115         .hasError("assignable");
116   }
117 
118   @Test
setElements_primitiveArgument()119   public void setElements_primitiveArgument() {
120     assertThatMethod("@Binds @ElementsIntoSet abstract Set<Number> bindInt(int integer);")
121         .hasError("assignable");
122   }
123 
124   @Test
elementsIntoSet_withRawSets()125   public void elementsIntoSet_withRawSets() {
126     assertThatMethod("@Binds @ElementsIntoSet abstract Set bindRawSet(HashSet hashSet);")
127         .hasError("cannot return a raw Set");
128   }
129 
130   @Test
intoMap_noMapKey()131   public void intoMap_noMapKey() {
132     assertThatMethod("@Binds @IntoMap abstract Object bindNoMapKey(String string);")
133         .hasError("methods of type map must declare a map key");
134   }
135 
136   @Test
intoMap_multipleMapKeys()137   public void intoMap_multipleMapKeys() {
138     assertThatMethod(
139             "@Binds @IntoMap @IntKey(1) @LongKey(2L) abstract Object manyMapKeys(String string);")
140         .importing(IntKey.class, LongKey.class)
141         .hasError("may not have more than one map key");
142   }
143 
assertThatMethod(String method)144   private DaggerModuleMethodSubject assertThatMethod(String method) {
145     return assertThatModuleMethod(method).withDeclaration(moduleDeclaration);
146   }
147 
148   @Qualifier
149   @Retention(RUNTIME)
150   public @interface Qualifier1 {}
151 
152   @Qualifier
153   @Retention(RUNTIME)
154   public @interface Qualifier2 {}
155 }
156