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