1 /* 2 * Copyright (C) 2020 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.hilt.android.processor.internal.aggregateddeps; 18 19 import static com.google.testing.compile.CompilationSubject.assertThat; 20 import static dagger.hilt.android.processor.AndroidCompilers.compiler; 21 22 import com.google.testing.compile.Compilation; 23 import com.google.testing.compile.JavaFileObjects; 24 import javax.tools.JavaFileObject; 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 import org.junit.runners.JUnit4; 28 29 @RunWith(JUnit4.class) 30 public class TestInstallInTest { 31 32 @Test testMissingValues()33 public void testMissingValues() { 34 JavaFileObject testInstallInModule = 35 JavaFileObjects.forSourceLines( 36 "test.TestInstallInModule", 37 "package test;", 38 "", 39 "import dagger.Module;", 40 "import dagger.hilt.testing.TestInstallIn;", 41 "", 42 "@Module", 43 "@TestInstallIn", 44 "interface TestInstallInModule {}"); 45 Compilation compilation = compiler().compile(testInstallInModule); 46 assertThat(compilation).failed(); 47 assertThat(compilation).hadErrorCount(1); 48 assertThat(compilation) 49 .hadErrorContaining( 50 "@dagger.hilt.testing.TestInstallIn is missing default values for elements " 51 + "components,replaces") 52 .inFile(testInstallInModule) 53 .onLine(7); 54 } 55 56 @Test testEmptyComponentValues()57 public void testEmptyComponentValues() { 58 JavaFileObject installInModule = 59 JavaFileObjects.forSourceLines( 60 "test.InstallInModule", 61 "package test;", 62 "", 63 "import dagger.Module;", 64 "import dagger.hilt.InstallIn;", 65 "import dagger.hilt.components.SingletonComponent;", 66 "", 67 "@Module", 68 "@InstallIn(SingletonComponent.class)", 69 "interface InstallInModule {}"); 70 JavaFileObject testInstallInModule = 71 JavaFileObjects.forSourceLines( 72 "test.TestInstallInModule", 73 "package test;", 74 "", 75 "import dagger.Module;", 76 "import dagger.hilt.testing.TestInstallIn;", 77 "", 78 "@Module", 79 "@TestInstallIn(components = {}, replaces = InstallInModule.class)", 80 "interface TestInstallInModule {}"); 81 Compilation compilation = compiler().compile(installInModule, testInstallInModule); 82 assertThat(compilation).failed(); 83 assertThat(compilation).hadErrorCount(1); 84 // TODO(bcorso): Add inFile().onLine() whenever we've fixed Processors.getAnnotationClassValues 85 assertThat(compilation) 86 .hadErrorContaining( 87 "@TestInstallIn, 'components' class is invalid or missing: " 88 + "@dagger.hilt.testing.TestInstallIn(" 89 + "components={}, replaces={test.InstallInModule.class})"); 90 } 91 92 @Test testEmptyReplacesValues()93 public void testEmptyReplacesValues() { 94 JavaFileObject testInstallInModule = 95 JavaFileObjects.forSourceLines( 96 "test.TestInstallInModule", 97 "package test;", 98 "", 99 "import dagger.Module;", 100 "import dagger.hilt.testing.TestInstallIn;", 101 "import dagger.hilt.components.SingletonComponent;", 102 "", 103 "@Module", 104 "@TestInstallIn(components = SingletonComponent.class, replaces = {})", 105 "interface TestInstallInModule {}"); 106 Compilation compilation = compiler().compile(testInstallInModule); 107 assertThat(compilation).failed(); 108 assertThat(compilation).hadErrorCount(1); 109 // TODO(bcorso): Add inFile().onLine() whenever we've fixed Processors.getAnnotationClassValues 110 assertThat(compilation) 111 .hadErrorContaining( 112 "@TestInstallIn, 'replaces' class is invalid or missing: " 113 + "@dagger.hilt.testing.TestInstallIn(" 114 + "components={dagger.hilt.components.SingletonComponent.class}, replaces={})"); 115 } 116 117 @Test testMissingModuleAnnotation()118 public void testMissingModuleAnnotation() { 119 JavaFileObject installInModule = 120 JavaFileObjects.forSourceLines( 121 "test.InstallInModule", 122 "package test;", 123 "", 124 "import dagger.Module;", 125 "import dagger.hilt.InstallIn;", 126 "import dagger.hilt.components.SingletonComponent;", 127 "", 128 "@Module", 129 "@InstallIn(SingletonComponent.class)", 130 "interface InstallInModule {}"); 131 JavaFileObject testInstallInModule = 132 JavaFileObjects.forSourceLines( 133 "test.TestInstallInModule", 134 "package test;", 135 "", 136 "import dagger.Module;", 137 "import dagger.hilt.components.SingletonComponent;", 138 "import dagger.hilt.testing.TestInstallIn;", 139 "", 140 "@TestInstallIn(", 141 " components = SingletonComponent.class,", 142 " replaces = InstallInModule.class)", 143 "interface TestInstallInModule {}"); 144 Compilation compilation = compiler().compile(installInModule, testInstallInModule); 145 assertThat(compilation).failed(); 146 assertThat(compilation).hadErrorCount(1); 147 assertThat(compilation) 148 .hadErrorContaining( 149 "@TestInstallIn-annotated classes must also be annotated with @Module or @EntryPoint: " 150 + "test.TestInstallInModule") 151 .inFile(testInstallInModule) 152 .onLine(10); 153 } 154 155 @Test testInvalidUsageOnEntryPoint()156 public void testInvalidUsageOnEntryPoint() { 157 JavaFileObject installInModule = 158 JavaFileObjects.forSourceLines( 159 "test.InstallInModule", 160 "package test;", 161 "", 162 "import dagger.Module;", 163 "import dagger.hilt.InstallIn;", 164 "import dagger.hilt.components.SingletonComponent;", 165 "", 166 "@Module", 167 "@InstallIn(SingletonComponent.class)", 168 "interface InstallInModule {}"); 169 JavaFileObject testInstallInEntryPoint = 170 JavaFileObjects.forSourceLines( 171 "test.TestInstallInEntryPoint", 172 "package test;", 173 "", 174 "import dagger.hilt.EntryPoint;", 175 "import dagger.hilt.components.SingletonComponent;", 176 "import dagger.hilt.testing.TestInstallIn;", 177 "", 178 "@EntryPoint", 179 "@TestInstallIn(", 180 " components = SingletonComponent.class,", 181 " replaces = InstallInModule.class)", 182 "interface TestInstallInEntryPoint {}"); 183 Compilation compilation = compiler().compile(installInModule, testInstallInEntryPoint); 184 assertThat(compilation).failed(); 185 assertThat(compilation).hadErrorCount(1); 186 assertThat(compilation) 187 .hadErrorContaining("@TestInstallIn can only be used with modules") 188 .inFile(testInstallInEntryPoint) 189 .onLine(11); 190 } 191 192 @Test testInvalidReplaceModules()193 public void testInvalidReplaceModules() { 194 JavaFileObject foo = 195 JavaFileObjects.forSourceLines("test.Foo", "package test;", "", "class Foo {}"); 196 JavaFileObject testInstallInModule = 197 JavaFileObjects.forSourceLines( 198 "test.TestInstallInModule", 199 "package test;", 200 "", 201 "import dagger.Module;", 202 "import dagger.hilt.components.SingletonComponent;", 203 "import dagger.hilt.testing.TestInstallIn;", 204 "", 205 "@Module", 206 "@TestInstallIn(", 207 " components = SingletonComponent.class,", 208 " replaces = Foo.class)", 209 "interface TestInstallInModule {}"); 210 Compilation compilation = compiler().compile(foo, testInstallInModule); 211 assertThat(compilation).failed(); 212 assertThat(compilation).hadErrorCount(1); 213 assertThat(compilation) 214 .hadErrorContaining( 215 "@TestInstallIn#replaces() can only contain @InstallIn modules, but found: [test.Foo]") 216 .inFile(testInstallInModule) 217 .onLine(11); 218 } 219 220 @Test testInternalDaggerReplaceModules()221 public void testInternalDaggerReplaceModules() { 222 JavaFileObject testInstallInModule = 223 JavaFileObjects.forSourceLines( 224 "test.TestInstallInModule", 225 "package test;", 226 "", 227 "import dagger.Module;", 228 "import dagger.hilt.components.SingletonComponent;", 229 "import dagger.hilt.testing.TestInstallIn;", 230 "", 231 "@Module", 232 "@TestInstallIn(", 233 " components = SingletonComponent.class,", 234 " replaces = dagger.hilt.android.internal.modules.ApplicationContextModule.class)", 235 "interface TestInstallInModule {}"); 236 Compilation compilation = compiler().compile(testInstallInModule); 237 assertThat(compilation).failed(); 238 assertThat(compilation).hadErrorCount(1); 239 assertThat(compilation) 240 .hadErrorContaining( 241 "@TestInstallIn#replaces() cannot contain internal Hilt modules, but found: " 242 + "[dagger.hilt.android.internal.modules.ApplicationContextModule]") 243 .inFile(testInstallInModule) 244 .onLine(11); 245 } 246 247 @Test testHiltWrapperDaggerReplaceModules()248 public void testHiltWrapperDaggerReplaceModules() { 249 JavaFileObject testInstallInModule = 250 JavaFileObjects.forSourceLines( 251 "test.TestInstallInModule", 252 "package test;", 253 "", 254 "import dagger.Module;", 255 "import dagger.hilt.components.SingletonComponent;", 256 "import dagger.hilt.testing.TestInstallIn;", 257 "import" 258 + " dagger.hilt.android.processor.internal.aggregateddeps.HiltWrapper_InstallInModule;", 259 "", 260 "@Module", 261 "@TestInstallIn(", 262 " components = SingletonComponent.class,", 263 // Note: this module is built in a separate library since AggregatedDepsProcessor can't 264 // handle modules generated in the same round. 265 " replaces = HiltWrapper_InstallInModule.class)", 266 "interface TestInstallInModule {}"); 267 Compilation compilation = compiler().compile(testInstallInModule); 268 assertThat(compilation).failed(); 269 assertThat(compilation).hadErrorCount(1); 270 assertThat(compilation) 271 .hadErrorContaining( 272 "@TestInstallIn#replaces() cannot contain Hilt generated public wrapper modules, " 273 + "but found: [dagger.hilt.android.processor.internal.aggregateddeps." 274 + "HiltWrapper_InstallInModule]") 275 .inFile(testInstallInModule) 276 .onLine(12); 277 } 278 279 @Test testCannotReplaceLocalInstallInModule()280 public void testCannotReplaceLocalInstallInModule() { 281 JavaFileObject test = 282 JavaFileObjects.forSourceLines( 283 "test.MyTest", 284 "package test;", 285 "", 286 "import dagger.Module;", 287 "import dagger.hilt.InstallIn;", 288 "import dagger.hilt.components.SingletonComponent;", 289 "import dagger.hilt.testing.TestInstallIn;", 290 "import dagger.hilt.android.testing.HiltAndroidTest;", 291 "", 292 "@HiltAndroidTest", 293 "public class MyTest {", 294 " @Module", 295 " @InstallIn(SingletonComponent.class)", 296 " interface LocalInstallInModule {}", 297 "}"); 298 JavaFileObject testInstallIn = 299 JavaFileObjects.forSourceLines( 300 "test.TestInstallInModule", 301 "package test;", 302 "", 303 "import dagger.Module;", 304 "import dagger.hilt.components.SingletonComponent;", 305 "import dagger.hilt.testing.TestInstallIn;", 306 "", 307 "@Module", 308 "@TestInstallIn(", 309 " components = SingletonComponent.class,", 310 " replaces = MyTest.LocalInstallInModule.class)", 311 "interface TestInstallInModule {}"); 312 Compilation compilation = compiler().compile(test, testInstallIn); 313 assertThat(compilation).failed(); 314 assertThat(compilation).hadErrorCount(1); 315 assertThat(compilation) 316 .hadErrorContaining( 317 "TestInstallIn#replaces() cannot replace test specific @InstallIn modules, but found: " 318 + "[test.MyTest.LocalInstallInModule].") 319 .inFile(testInstallIn) 320 .onLine(11); 321 } 322 323 @Test testThatTestInstallInCannotOriginateFromTest()324 public void testThatTestInstallInCannotOriginateFromTest() { 325 JavaFileObject installInModule = 326 JavaFileObjects.forSourceLines( 327 "test.InstallInModule", 328 "package test;", 329 "", 330 "import dagger.Module;", 331 "import dagger.hilt.InstallIn;", 332 "import dagger.hilt.components.SingletonComponent;", 333 "", 334 "@Module", 335 "@InstallIn(SingletonComponent.class)", 336 "interface InstallInModule {}"); 337 JavaFileObject test = 338 JavaFileObjects.forSourceLines( 339 "test.MyTest", 340 "package test;", 341 "", 342 "import dagger.Module;", 343 "import dagger.hilt.components.SingletonComponent;", 344 "import dagger.hilt.testing.TestInstallIn;", 345 "import dagger.hilt.android.testing.HiltAndroidTest;", 346 "", 347 "@HiltAndroidTest", 348 "public class MyTest {", 349 " @Module", 350 " @TestInstallIn(", 351 " components = SingletonComponent.class,", 352 " replaces = InstallInModule.class)", 353 " interface TestInstallInModule {}", 354 "}"); 355 Compilation compilation = compiler().compile(test, installInModule); 356 assertThat(compilation).failed(); 357 assertThat(compilation).hadErrorCount(1); 358 assertThat(compilation) 359 .hadErrorContaining( 360 "@TestInstallIn modules cannot be nested in (or originate from) a " 361 + "@HiltAndroidTest-annotated class: test.MyTest") 362 .inFile(test) 363 .onLine(14); 364 } 365 } 366