• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.testing.compile.CompilationSubject.assertThat;
20 import static dagger.internal.codegen.Compilers.daggerCompiler;
21 import static dagger.internal.codegen.TestUtils.message;
22 
23 import com.google.testing.compile.Compilation;
24 import com.google.testing.compile.JavaFileObjects;
25 import javax.tools.JavaFileObject;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 import org.junit.runners.JUnit4;
29 
30 /**
31  * Tests that errors are reported correctly when a {@code @Binds} method's delegate (the type of its
32  * parameter) is missing.
33  */
34 @RunWith(JUnit4.class)
35 public class BindsMissingDelegateValidationTest {
36   @Test
bindsMissingDelegate()37   public void bindsMissingDelegate() {
38     JavaFileObject component =
39         JavaFileObjects.forSourceLines(
40             "test.C",
41             "package test;",
42             "",
43             "import dagger.Binds;",
44             "import dagger.Component;",
45             "import dagger.Module;",
46             "",
47             "@Component(modules = C.TestModule.class)",
48             "interface C {",
49             "  Object object();",
50             "",
51             "  static class NotBound {}",
52             "",
53             "  @Module",
54             "  abstract static class TestModule {",
55             "    @Binds abstract Object bindObject(NotBound notBound);",
56             "  }",
57             "}");
58 
59     Compilation compilation = daggerCompiler().compile(component);
60     assertThat(compilation).failed();
61     assertThat(compilation)
62         .hadErrorContaining("test.C.NotBound cannot be provided")
63         .inFile(component)
64         .onLineContaining("interface C");
65   }
66 
67   @Test
bindsMissingDelegate_duplicateBinding()68   public void bindsMissingDelegate_duplicateBinding() {
69     JavaFileObject component =
70         JavaFileObjects.forSourceLines(
71             "test.C",
72             "package test;",
73             "",
74             "import dagger.Binds;",
75             "import dagger.Component;",
76             "import dagger.Module;",
77             "import dagger.Provides;",
78             "",
79             "@Component(modules = C.TestModule.class)",
80             "interface C {",
81             "  Object object();",
82             "",
83             "  static class NotBound {}",
84             "",
85             "  @Module",
86             "  abstract static class TestModule {",
87             "    @Binds abstract Object bindObject(NotBound notBound);",
88             "    @Provides static Object provideObject() { return new Object(); }",
89             "  }",
90             "}");
91 
92     Compilation compilation = daggerCompiler().compile(component);
93     assertThat(compilation).failed();
94     // Some javacs report only the first error for each source line.
95     // Assert that one of the expected errors is reported.
96     assertThat(compilation)
97         .hadErrorContainingMatch(
98             "\\Qtest.C.NotBound cannot be provided\\E|"
99                 + message(
100                     "\\Qjava.lang.Object is bound multiple times:",
101                     "    @Binds Object test.C.TestModule.bindObject(test.C.NotBound)",
102                     "    @Provides Object test.C.TestModule.provideObject()\\E"))
103         .inFile(component)
104         .onLineContaining("interface C");
105   }
106 
107   @Test
bindsMissingDelegate_setBinding()108   public void bindsMissingDelegate_setBinding() {
109     JavaFileObject component =
110         JavaFileObjects.forSourceLines(
111             "test.C",
112             "package test;",
113             "",
114             "import dagger.Binds;",
115             "import dagger.Component;",
116             "import dagger.Module;",
117             "import dagger.multibindings.IntoSet;",
118             "import java.util.Set;",
119             "",
120             "@Component(modules = C.TestModule.class)",
121             "interface C {",
122             "  Set<Object> objects();",
123             "",
124             "  static class NotBound {}",
125             "",
126             "  @Module",
127             "  abstract static class TestModule {",
128             "    @Binds @IntoSet abstract Object bindObject(NotBound notBound);",
129             "  }",
130             "}");
131 
132     Compilation compilation = daggerCompiler().compile(component);
133     assertThat(compilation).failed();
134     assertThat(compilation)
135         .hadErrorContaining("test.C.NotBound cannot be provided")
136         .inFile(component)
137         .onLineContaining("interface C");
138   }
139 
140   @Test
bindsMissingDelegate_mapBinding()141   public void bindsMissingDelegate_mapBinding() {
142     JavaFileObject component =
143         JavaFileObjects.forSourceLines(
144             "test.C",
145             "package test;",
146             "",
147             "import dagger.Binds;",
148             "import dagger.Component;",
149             "import dagger.Module;",
150             "import dagger.multibindings.IntoMap;",
151             "import dagger.multibindings.StringKey;",
152             "import java.util.Map;",
153             "",
154             "@Component(modules = C.TestModule.class)",
155             "interface C {",
156             "  Map<String, Object> objects();",
157             "",
158             "  static class NotBound {}",
159             "",
160             "  @Module",
161             "  abstract static class TestModule {",
162             "    @Binds @IntoMap @StringKey(\"key\")",
163             "    abstract Object bindObject(NotBound notBound);",
164             "  }",
165             "}");
166 
167     Compilation compilation = daggerCompiler().compile(component);
168     assertThat(compilation).failed();
169     assertThat(compilation)
170         .hadErrorContaining("test.C.NotBound cannot be provided")
171         .inFile(component)
172         .onLineContaining("interface C");
173   }
174 
175   @Test
bindsMissingDelegate_mapBinding_sameKey()176   public void bindsMissingDelegate_mapBinding_sameKey() {
177     JavaFileObject component =
178         JavaFileObjects.forSourceLines(
179             "test.C",
180             "package test;",
181             "",
182             "import dagger.Binds;",
183             "import dagger.Component;",
184             "import dagger.Module;",
185             "import dagger.Provides;",
186             "import dagger.multibindings.IntoMap;",
187             "import dagger.multibindings.StringKey;",
188             "import java.util.Map;",
189             "",
190             "@Component(modules = C.TestModule.class)",
191             "interface C {",
192             "  Map<String, Object> objects();",
193             "",
194             "  static class NotBound {}",
195             "",
196             "  @Module",
197             "  abstract static class TestModule {",
198             "    @Binds @IntoMap @StringKey(\"key\")",
199             "    abstract Object bindObject(NotBound notBound);",
200             "",
201             "    @Provides @IntoMap @StringKey(\"key\")",
202             "    static Object provideObject() { return new Object(); }",
203             "  }",
204             "}");
205 
206     Compilation compilation = daggerCompiler().compile(component);
207     assertThat(compilation).failed();
208     // Some javacs report only the first error for each source line.
209     assertThat(compilation)
210         .hadErrorContainingMatch(
211             "\\Qtest.C.NotBound cannot be provided\\E|"
212                 + "\\Qsame map key is bound more than once\\E")
213         .inFile(component)
214         .onLineContaining("interface C");
215   }
216 }
217