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.internal.codegen; 18 19 import androidx.room.compiler.processing.util.Source; 20 import com.google.common.collect.ImmutableCollection; 21 import dagger.testing.compile.CompilerTests; 22 import dagger.testing.golden.GoldenFileRule; 23 import org.junit.Rule; 24 import org.junit.Test; 25 import org.junit.runner.RunWith; 26 import org.junit.runners.Parameterized; 27 import org.junit.runners.Parameterized.Parameters; 28 29 @RunWith(Parameterized.class) 30 public class AssistedFactoryTest { 31 @Parameters(name = "{0}") parameters()32 public static ImmutableCollection<Object[]> parameters() { 33 return CompilerMode.TEST_PARAMETERS; 34 } 35 36 @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule(); 37 38 private final CompilerMode compilerMode; 39 AssistedFactoryTest(CompilerMode compilerMode)40 public AssistedFactoryTest(CompilerMode compilerMode) { 41 this.compilerMode = compilerMode; 42 } 43 44 @Test testAssistedFactory()45 public void testAssistedFactory() throws Exception { 46 Source foo = 47 CompilerTests.javaSource( 48 "test.Foo", 49 "package test;", 50 "", 51 "import dagger.assisted.Assisted;", 52 "import dagger.assisted.AssistedInject;", 53 "", 54 "class Foo {", 55 " @AssistedInject", 56 " Foo(@Assisted String str, Bar bar) {}", 57 "}"); 58 59 Source fooFactory = 60 CompilerTests.javaSource( 61 "test.FooFactory", 62 "package test;", 63 "", 64 "import dagger.assisted.AssistedFactory;", 65 "", 66 "@AssistedFactory", 67 "interface FooFactory {", 68 " Foo create(String factoryStr);", 69 "}"); 70 71 Source bar = 72 CompilerTests.javaSource( 73 "test.Bar", 74 "package test;", 75 "", 76 "import javax.inject.Inject;", 77 "", 78 "class Bar {", 79 " @Inject Bar() {}", 80 "}"); 81 82 Source component = 83 CompilerTests.javaSource( 84 "test.TestComponent", 85 "package test;", 86 "", 87 "import dagger.Component;", 88 "", 89 "@Component", 90 "interface TestComponent {", 91 " FooFactory fooFactory();", 92 "}"); 93 94 CompilerTests.daggerCompiler(foo, bar, fooFactory, component) 95 .withProcessingOptions(compilerMode.processorOptions()) 96 .compile( 97 subject -> { 98 subject.hasErrorCount(0); 99 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 100 }); 101 } 102 103 @Test testAssistedFactoryCycle()104 public void testAssistedFactoryCycle() throws Exception { 105 Source foo = 106 CompilerTests.javaSource( 107 "test.Foo", 108 "package test;", 109 "", 110 "import dagger.assisted.Assisted;", 111 "import dagger.assisted.AssistedInject;", 112 "", 113 "class Foo {", 114 " @AssistedInject", 115 " Foo(@Assisted String str, Bar bar) {}", 116 "}"); 117 118 Source fooFactory = 119 CompilerTests.javaSource( 120 "test.FooFactory", 121 "package test;", 122 "", 123 "import dagger.assisted.AssistedFactory;", 124 "", 125 "@AssistedFactory", 126 "interface FooFactory {", 127 " Foo create(String factoryStr);", 128 "}"); 129 130 Source bar = 131 CompilerTests.javaSource( 132 "test.Bar", 133 "package test;", 134 "", 135 "import javax.inject.Inject;", 136 "", 137 "class Bar {", 138 " @Inject Bar(FooFactory fooFactory) {}", 139 "}"); 140 141 Source component = 142 CompilerTests.javaSource( 143 "test.TestComponent", 144 "package test;", 145 "", 146 "import dagger.Component;", 147 "", 148 "@Component", 149 "interface TestComponent {", 150 " FooFactory fooFactory();", 151 "}"); 152 153 CompilerTests.daggerCompiler(foo, bar, fooFactory, component) 154 .withProcessingOptions(compilerMode.processorOptions()) 155 .compile( 156 subject -> { 157 subject.hasErrorCount(0); 158 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 159 }); 160 } 161 162 @Test assistedParamConflictsWithComponentFieldName_successfulyDeduped()163 public void assistedParamConflictsWithComponentFieldName_successfulyDeduped() throws Exception { 164 Source foo = 165 CompilerTests.javaSource( 166 "test.Foo", 167 "package test;", 168 "", 169 "import dagger.assisted.Assisted;", 170 "import dagger.assisted.AssistedInject;", 171 "import javax.inject.Provider;", 172 "", 173 "class Foo {", 174 " @AssistedInject", 175 " Foo(@Assisted String testComponentImpl, Provider<Bar> bar) {}", 176 "}"); 177 178 Source fooFactory = 179 CompilerTests.javaSource( 180 "test.FooFactory", 181 "package test;", 182 "", 183 "import dagger.assisted.AssistedFactory;", 184 "", 185 "@AssistedFactory", 186 "interface FooFactory {", 187 " Foo create(String factoryStr);", 188 "}"); 189 190 Source bar = 191 CompilerTests.javaSource( 192 "test.Bar", 193 "package test;", 194 "", 195 "import javax.inject.Inject;", 196 "", 197 "class Bar {", 198 " @Inject Bar() {}", 199 "}"); 200 201 Source component = 202 CompilerTests.javaSource( 203 "test.TestComponent", 204 "package test;", 205 "", 206 "import dagger.Component;", 207 "", 208 "@Component", 209 "interface TestComponent {", 210 " FooFactory fooFactory();", 211 "}"); 212 213 CompilerTests.daggerCompiler(foo, bar, fooFactory, component) 214 .withProcessingOptions(compilerMode.processorOptions()) 215 .compile( 216 subject -> { 217 subject.hasErrorCount(0); 218 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 219 }); 220 } 221 222 @Test testFactoryGeneratorDuplicatedParamNames()223 public void testFactoryGeneratorDuplicatedParamNames() throws Exception { 224 Source component = 225 CompilerTests.javaSource( 226 "test.TestComponent", 227 "package test;", 228 "", 229 "import dagger.BindsInstance;", 230 "import dagger.Component;", 231 "", 232 "@Component", 233 "interface TestComponent {", 234 " @Component.Factory", 235 " interface Factory {", 236 " TestComponent create(@BindsInstance Bar arg);", 237 "}", 238 " FooFactory getFooFactory();", 239 "}"); 240 241 Source fooFactory = 242 CompilerTests.javaSource( 243 "test.FooFactory", 244 "package test;", 245 "", 246 "import dagger.assisted.AssistedFactory;", 247 "", 248 "@AssistedFactory", 249 "public interface FooFactory {", 250 " Foo create(Integer arg);", 251 "}"); 252 253 Source bar = 254 CompilerTests.javaSource( 255 "test.Bar", 256 "package test;", 257 "", 258 "interface Bar {}"); 259 260 Source foo = 261 CompilerTests.javaSource( 262 "test.Foo", 263 "package test;", 264 "", 265 "import dagger.assisted.Assisted;", 266 "import dagger.assisted.AssistedInject;", 267 "", 268 "class Foo {", 269 " @AssistedInject", 270 " Foo(Bar arg, @Assisted Integer argProvider) {}", 271 "}"); 272 273 CompilerTests.daggerCompiler(component, fooFactory, foo, bar) 274 .withProcessingOptions(compilerMode.processorOptions()) 275 .compile( 276 subject -> { 277 subject.hasErrorCount(0); 278 subject.generatedSource(goldenFileRule.goldenSource("test/Foo_Factory")); 279 }); 280 } 281 282 @Test testParameterizedAssistParam()283 public void testParameterizedAssistParam() throws Exception { 284 Source component = 285 CompilerTests.javaSource( 286 "test.TestComponent", 287 "package test;", 288 "", 289 "import dagger.Component;", 290 "", 291 "@Component", 292 "interface TestComponent {", 293 " FooFactory<String> getFooFactory();", 294 "}"); 295 296 Source fooFactory = 297 CompilerTests.javaSource( 298 "test.FooFactory", 299 "package test;", 300 "", 301 "import dagger.assisted.AssistedFactory;", 302 "", 303 "@AssistedFactory", 304 "public interface FooFactory<T> {", 305 " Foo<T> create(T arg);", 306 "}"); 307 308 Source foo = 309 CompilerTests.javaSource( 310 "test.Foo", 311 "package test;", 312 "", 313 "import dagger.assisted.Assisted;", 314 "import dagger.assisted.AssistedInject;", 315 "", 316 "class Foo<T> {", 317 " @AssistedInject", 318 " Foo(@Assisted T arg) {}", 319 "}"); 320 321 CompilerTests.daggerCompiler(component, fooFactory, foo) 322 .withProcessingOptions(compilerMode.processorOptions()) 323 .compile( 324 subject -> { 325 subject.hasErrorCount(0); 326 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 327 }); 328 } 329 330 // This is a regression test for b/305748522 331 // The important thing for this test is that we have two assisted factories for the same assisted 332 // injection class and that they are requested in different components. 333 @Test testMultipleAssistedFactoryInDifferentComponents()334 public void testMultipleAssistedFactoryInDifferentComponents() throws Exception { 335 Source component = 336 CompilerTests.javaSource( 337 "test.MyComponent", 338 "package test;", 339 "", 340 "import dagger.Component;", 341 "", 342 "@Component", 343 "interface MyComponent {", 344 " MyComponentAssistedFactory myComponentAssistedFactory();", 345 " MySubcomponent mySubcomponent();", 346 "}"); 347 Source subcomponent = 348 CompilerTests.javaSource( 349 "test.MySubcomponent", 350 "package test;", 351 "", 352 "import dagger.Subcomponent;", 353 "", 354 "@Subcomponent", 355 "interface MySubcomponent {", 356 " MySubcomponentAssistedFactory mySubcomponentAssistedFactory();", 357 "}"); 358 Source assistedClass = 359 CompilerTests.javaSource( 360 "test.MyAssistedClass", 361 "package test;", 362 "", 363 "import dagger.assisted.Assisted;", 364 "import dagger.assisted.AssistedInject;", 365 "", 366 "final class MyAssistedClass {", 367 " private final Foo foo;", 368 " private final Bar bar;", 369 "", 370 " @AssistedInject", 371 " MyAssistedClass(@Assisted Foo foo, Baz baz, @Assisted Bar bar) {", 372 " this.foo = foo;", 373 " this.bar = bar;", 374 " }", 375 "}"); 376 Source componentAssistedFactory = 377 CompilerTests.javaSource( 378 "test.MyComponentAssistedFactory", 379 "package test;", 380 "", 381 "import dagger.assisted.AssistedFactory;", 382 "", 383 "@AssistedFactory", 384 "interface MyComponentAssistedFactory {", 385 " MyAssistedClass create(Bar bar, Foo foo);", 386 "}"); 387 Source subcomponentAssistedFactory = 388 CompilerTests.javaSource( 389 "test.MySubcomponentAssistedFactory", 390 "package test;", 391 "", 392 "import dagger.assisted.AssistedFactory;", 393 "", 394 "@AssistedFactory", 395 "interface MySubcomponentAssistedFactory {", 396 " MyAssistedClass create(Bar bar, Foo foo);", 397 "}"); 398 Source foo = 399 CompilerTests.javaSource( 400 "test.Foo", 401 "package test;", 402 "final class Foo {}"); 403 Source bar = 404 CompilerTests.javaSource( 405 "test.Bar", 406 "package test;", 407 "final class Bar {}"); 408 Source baz = 409 CompilerTests.javaSource( 410 "test.Baz", 411 "package test;", 412 "", 413 "import javax.inject.Inject;", 414 "", 415 "final class Baz {", 416 " @Inject Baz() {}", 417 "}"); 418 419 CompilerTests.daggerCompiler( 420 component, 421 subcomponent, 422 assistedClass, 423 componentAssistedFactory, 424 subcomponentAssistedFactory, 425 foo, 426 bar, 427 baz) 428 .withProcessingOptions(compilerMode.processorOptions()) 429 .compile( 430 subject -> { 431 subject.hasErrorCount(0); 432 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerMyComponent")); 433 }); 434 } 435 } 436