xref: /aosp_15_r20/external/dagger2/javatests/dagger/functional/kotlinsrc/builder/BuilderTest.kt (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
2  * Copyright (C) 2022 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.functional.kotlinsrc.builder
18 
19 import com.google.common.truth.Truth.assertThat
20 import dagger.Component
21 import dagger.Module
22 import dagger.Provides
23 import dagger.Subcomponent
24 import java.lang.annotation.Retention
25 import java.lang.annotation.RetentionPolicy
26 import javax.inject.Inject
27 import javax.inject.Provider
28 import javax.inject.Scope
29 import javax.inject.Singleton
30 import org.junit.Assert.fail
31 import org.junit.Test
32 import org.junit.runner.RunWith
33 import org.junit.runners.JUnit4
34 
35 @RunWith(JUnit4::class)
36 class BuilderTest {
37   @Subcomponent(
38     modules =
39       [
40         StringModule::class,
41         IntModuleIncludingDoubleAndFloat::class,
42         LongModule::class,
43         ByteModule::class
44       ]
45   )
46   internal interface TestChildComponentWithBuilderAbstractClass {
snull47     fun s(): String
48     fun i(): Int
49     fun l(): Long
50     fun f(): Float
51     fun d(): Double
52     fun b(): Byte
53     abstract class SharedBuilder<B, C, M1, M2> {
54       abstract fun build(): C // Test resolving return type of build()
55       abstract fun setM1(m1: M1): B // Test resolving return type & param of setter
56       abstract fun setM2(m2: M2): SharedBuilder<B, C, M1, M2> // Test being overridden
57       abstract fun setM3(doubleModule: DoubleModule) // Test being overridden
58       abstract fun set(
59         floatModule: FloatModule
60       ): SharedBuilder<B, C, M1, M2> // Test returning supertype.
61     }
62 
63     @Subcomponent.Builder
64     abstract class Builder :
65       TestChildComponentWithBuilderAbstractClass.SharedBuilder<
66         Builder,
67         TestChildComponentWithBuilderAbstractClass,
68         StringModule,
69         IntModuleIncludingDoubleAndFloat
70       >() {
setM2null71       abstract override fun setM2(m2: IntModuleIncludingDoubleAndFloat): Builder // Test covariance
72       abstract override fun setM3(doubleModule: DoubleModule) // Test simple overrides allowed
73       abstract fun set(byteModule: ByteModule) // Note we're missing LongModule -- it's implicit
74     }
75   }
76 
77   @Subcomponent(
78     modules =
79       [
80         StringModule::class,
81         IntModuleIncludingDoubleAndFloat::class,
82         LongModule::class,
83         ByteModule::class
84       ]
85   )
86   internal interface TestChildComponentWithBuilderInterface {
87     fun s(): String
88     fun i(): Int
89     fun l(): Long
90     fun f(): Float
91     fun d(): Double
92     fun b(): Byte
93     interface SharedBuilder<B, C, M1, M2> {
94       fun build(): C // Test resolving return type of build()
95       fun setM1(m1: M1): B // Test resolving return type & param of setter
96       fun setM2(m2: M2): SharedBuilder<B, C, M1, M2> // Test being overridden
97       fun setM3(doubleModule: DoubleModule) // Test being overridden
98       fun set(
99         floatModule: FloatModule
100       ): SharedBuilder<B, C, M1, M2> // Test return type is supertype.
101     }
102 
103     @Subcomponent.Builder
104     interface Builder :
105       TestChildComponentWithBuilderInterface.SharedBuilder<
106         Builder,
107         TestChildComponentWithBuilderInterface,
108         StringModule,
109         IntModuleIncludingDoubleAndFloat
110       > {
111       override fun setM2(m2: IntModuleIncludingDoubleAndFloat): Builder // Test covariant overrides
112       override fun setM3(doubleModule: DoubleModule) // Test simple overrides allowed
113       fun set(byteModule: ByteModule) // Note we're missing LongModule -- it's implicit
114     }
115   }
116 
117   @Component(
118     modules = [StringModule::class, IntModuleIncludingDoubleAndFloat::class, LongModule::class],
119     dependencies = [DepComponent::class]
120   )
121   internal abstract class TestComponentWithBuilderAbstractClass {
snull122     abstract fun s(): String
123     abstract fun i(): Int
124     abstract fun l(): Long
125     abstract fun f(): Float
126     abstract fun d(): Double
127     internal abstract class SharedBuilder {
128       // Make sure we use the overriding signature.
129       abstract fun build(): Any
130       open fun stringModule(stringModule: StringModule): Any? = null
131       @Suppress("UNUSED_PARAMETER")
132       fun ignoredLongModule(longModule: LongModule): SharedBuilder? = null
133     }
134 
135     @Component.Builder
136     internal abstract class Builder : TestComponentWithBuilderAbstractClass.SharedBuilder() {
buildnull137       abstract override fun build(): TestComponentWithBuilderAbstractClass // Narrowing return type
138       abstract override fun stringModule(stringModule: StringModule): Builder // Abstract & narrow
139       abstract fun intModule(intModule: IntModuleIncludingDoubleAndFloat): Builder
140       abstract fun doubleModule(doubleModule: DoubleModule) // Module w/o args
141       abstract fun depComponent(depComponent: DepComponent)
142       // Note we're missing LongModule & FloatModule -- they/re implicit
143       @Suppress("UNUSED_PARAMETER")
144       fun ignoredIntModule(intModule: IntModuleIncludingDoubleAndFloat): Builder? = null
145     }
146 
147     companion object {
148       fun builder(): Builder = DaggerBuilderTest_TestComponentWithBuilderAbstractClass.builder()
149     }
150   }
151 
152   @Component(
153     modules = [StringModule::class, IntModuleIncludingDoubleAndFloat::class, LongModule::class],
154     dependencies = [DepComponent::class]
155   )
156   internal interface TestComponentWithBuilderInterface {
snull157     fun s(): String
158     fun i(): Int
159     fun l(): Long
160     fun f(): Float
161     fun d(): Double
162     interface SharedBuilder {
163       // Make sure we use the overriding signature.
164       fun build(): Any
165       fun stringModule(m1: StringModule): Any
166     }
167 
168     @Component.Builder
169     interface Builder : TestComponentWithBuilderInterface.SharedBuilder {
buildnull170       override fun build(): TestComponentWithBuilderInterface // Narrowing return type
171       override fun stringModule(m1: StringModule): Builder // Narrowing return type
172       fun intModule(intModule: IntModuleIncludingDoubleAndFloat): Builder
173       fun doubleModule(doubleModule: DoubleModule) // Module w/o args
174       fun depComponent(
175         depComponent: DepComponent
176       ) // Note we're missing LongModule & FloatModule -- they/re implicit
177     }
178   }
179 
180   @Component(
181     modules = [StringModule::class, IntModuleIncludingDoubleAndFloat::class, LongModule::class],
182     dependencies = [DepComponent::class]
183   )
184   internal interface TestComponentWithGenericBuilderAbstractClass {
185     fun s(): String
186     fun i(): Int
187     fun l(): Long
188     fun f(): Float
189     fun d(): Double
190     abstract class SharedBuilder<B, C, M1, M2> {
191       abstract fun build(): C // Test resolving return type of build()
192       abstract fun setM1(m1: M1): B // Test resolving return type & param of setter
193       abstract fun setM2(m2: M2): SharedBuilder<B, C, M1, M2> // Test being overridden
194       abstract fun doubleModule(doubleModule: DoubleModule) // Test being overridden
195       abstract fun depComponent(
196         floatModule: FloatModule
197       ): SharedBuilder<B, C, M1, M2> // Test return type
198     }
199 
200     @Component.Builder
201     abstract class Builder :
202       TestComponentWithGenericBuilderAbstractClass.SharedBuilder<
203         Builder,
204         TestComponentWithGenericBuilderAbstractClass,
205         StringModule,
206         IntModuleIncludingDoubleAndFloat
207       >() {
208       abstract override fun setM2(
209         m2: IntModuleIncludingDoubleAndFloat
210       ): Builder // Test covariant overrides
211       abstract override fun doubleModule(
212         doubleModule: DoubleModule
213       ) // Test simple overrides allowed
214       abstract fun depComponent(
215         depComponent: DepComponent
216       ) // Note we're missing LongModule & FloatModule -- they're implicit
217     }
218   }
219 
220   @Component(
221     modules = [StringModule::class, IntModuleIncludingDoubleAndFloat::class, LongModule::class],
222     dependencies = [DepComponent::class]
223   )
224   internal interface TestComponentWithGenericBuilderInterface {
snull225     fun s(): String
226     fun i(): Int
227     fun l(): Long
228     fun f(): Float
229     fun d(): Double
230     interface SharedBuilder<B, C, M1, M2> {
231       fun build(): C // Test resolving return type of build()
232       fun setM1(m1: M1): B // Test resolving return type & param of setter
233       fun setM2(m2: M2): SharedBuilder<B, C, M1, M2> // Test being overridden
234       fun doubleModule(doubleModule: DoubleModule) // Test being overridden
235       fun set(
236         floatModule: FloatModule
237       ): SharedBuilder<B, C, M1, M2> // Test return type is supertype.
238     }
239 
240     @Component.Builder
241     interface Builder :
242       TestComponentWithGenericBuilderInterface.SharedBuilder<
243         Builder,
244         TestComponentWithGenericBuilderInterface,
245         StringModule,
246         IntModuleIncludingDoubleAndFloat
247       > {
setM2null248       override fun setM2(
249         m2: IntModuleIncludingDoubleAndFloat
250       ): Builder // Test covariant overrides allowed
251       override fun doubleModule(doubleModule: DoubleModule) // Test simple overrides allowed
252       fun depComponent(depComponent: DepComponent) // Note we're missing M5 -- that's implicit.
253     }
254   }
255 
256   @Component internal interface DepComponent
257 
258   @Singleton
259   @Component
260   internal interface ParentComponent {
261     fun childAbstractClassBuilder(): TestChildComponentWithBuilderAbstractClass.Builder
262     fun childInterfaceBuilder(): TestChildComponentWithBuilderInterface.Builder
263     fun middleBuilder(): MiddleChild.Builder
264     fun otherBuilder(): OtherMiddleChild.Builder
265     fun requiresMiddleChildBuilder(): RequiresSubcomponentBuilder<MiddleChild.Builder>
266   }
267 
268   @Scope internal annotation class MiddleScope
269 
270   @MiddleScope
271   @Subcomponent(modules = [StringModule::class])
272   internal interface MiddleChild {
snull273     fun s(): String
274     fun grandchildBuilder(): Grandchild.Builder
275     fun requiresGrandchildBuilder(): RequiresSubcomponentBuilder<Grandchild.Builder>
276 
277     @Subcomponent.Builder
278     interface Builder {
279       fun build(): MiddleChild
280       fun set(stringModule: StringModule): Builder
281     }
282   }
283 
284   internal class RequiresSubcomponentBuilder<B>
285   @Inject
286   constructor(
287     private val subcomponentBuilderProvider: Provider<B>,
288     private val subcomponentBuilder: B
289   ) {
subcomponentBuilderProvidernull290     fun subcomponentBuilderProvider() = subcomponentBuilderProvider
291     fun subcomponentBuilder() = subcomponentBuilder
292   }
293 
294   @MiddleScope
295   @Subcomponent(modules = [StringModule::class, LongModule::class])
296   internal interface OtherMiddleChild {
297     fun l(): Long
298     fun s(): String
299     fun grandchildBuilder(): Grandchild.Builder
300 
301     @Subcomponent.Builder
302     interface Builder {
303       fun build(): OtherMiddleChild
304       fun set(stringModule: StringModule): Builder
305     }
306   }
307 
308   @Component(modules = [StringModule::class])
309   @Singleton
310   internal interface ParentOfGenericComponent : GenericParent<Grandchild.Builder>
311 
312   @Subcomponent(modules = [IntModuleIncludingDoubleAndFloat::class])
313   internal interface Grandchild {
inull314     fun i(): Int
315     fun s(): String
316 
317     @Subcomponent.Builder
318     interface Builder {
319       fun build(): Grandchild
320       fun set(intModule: IntModuleIncludingDoubleAndFloat): Builder
321     }
322   }
323 
324   internal interface GenericParent<B> {
subcomponentBuildernull325     fun subcomponentBuilder(): B
326   }
327 
328   @Module
329   internal class ByteModule(private val b: Byte) {
330     @Provides fun b(): Byte = b
331   }
332 
333   @Module
334   internal class DoubleModule {
dnull335     @Provides fun d(): Double = 4.2
336   }
337 
338   @Module
339   internal class LongModule {
340     @Provides fun l(): Long = 6L
341   }
342 
343   @Module
344   internal class FloatModule {
fnull345     @Provides fun f(): Float = 5.5f
346   }
347 
348   @Module
349   internal class StringModule(private val string: String) {
350     @Provides fun string(): String = string
351   }
352 
353   @Module(includes = [DoubleModule::class, FloatModule::class])
354   internal class IntModuleIncludingDoubleAndFloat(private val integer: Int) {
integernull355     @Provides fun integer(): Int = integer
356   }
357 
358   @Test
359   fun interfaceBuilder() {
360     val builder = DaggerBuilderTest_TestComponentWithBuilderInterface.builder()
361 
362     // Make sure things fail if we don't set our required modules.
363     try {
364       builder.build()
365       fail()
366     } catch (expected: IllegalStateException) {}
367 
368     builder
369       .intModule(IntModuleIncludingDoubleAndFloat(1))
370       .stringModule(StringModule("sam"))
371       .depComponent(object : DepComponent {})
372     builder.doubleModule(DoubleModule())
373 
374     // Don't set other modules -- make sure it works.
375     val component = builder.build()
376     assertThat(component.s()).isEqualTo("sam")
377     assertThat(component.i()).isEqualTo(1)
378     assertThat(component.d()).isEqualTo(4.2)
379     assertThat(component.f()).isEqualTo(5.5f)
380     assertThat(component.l()).isEqualTo(6L)
381   }
382 
383   @Test
abstractClassBuildernull384   fun abstractClassBuilder() {
385     val builder = TestComponentWithBuilderAbstractClass.builder()
386 
387     // Make sure things fail if we don't set our required modules.
388     try {
389       builder.build()
390       fail()
391     } catch (expected: IllegalStateException) {}
392 
393     builder
394       .intModule(IntModuleIncludingDoubleAndFloat(1))
395       .stringModule(StringModule("sam"))
396       .depComponent(object : DepComponent {})
397     builder.doubleModule(DoubleModule())
398 
399     // Don't set other modules -- make sure it works.
400     val component = builder.build()
401     assertThat(component.s()).isEqualTo("sam")
402     assertThat(component.i()).isEqualTo(1)
403     assertThat(component.d()).isEqualTo(4.2)
404     assertThat(component.f()).isEqualTo(5.5f)
405     assertThat(component.l()).isEqualTo(6L)
406   }
407 
408   @Test
interfaceGenericBuildernull409   fun interfaceGenericBuilder() {
410     val builder = DaggerBuilderTest_TestComponentWithGenericBuilderInterface.builder()
411 
412     // Make sure things fail if we don't set our required modules.
413     try {
414       builder.build()
415       fail()
416     } catch (expected: IllegalStateException) {}
417 
418     builder
419       .setM2(IntModuleIncludingDoubleAndFloat(1))
420       .setM1(StringModule("sam"))
421       .depComponent(object : DepComponent {})
422     builder.doubleModule(DoubleModule())
423 
424     // Don't set other modules -- make sure it works.
425     val component = builder.build()
426     assertThat(component.s()).isEqualTo("sam")
427     assertThat(component.i()).isEqualTo(1)
428     assertThat(component.d()).isEqualTo(4.2)
429     assertThat(component.f()).isEqualTo(5.5f)
430     assertThat(component.l()).isEqualTo(6L)
431   }
432 
433   @Test
abstractClassGenericBuildernull434   fun abstractClassGenericBuilder() {
435     val builder = DaggerBuilderTest_TestComponentWithGenericBuilderAbstractClass.builder()
436 
437     // Make sure things fail if we don't set our required modules.
438     try {
439       builder.build()
440       fail()
441     } catch (expected: IllegalStateException) {}
442 
443     builder
444       .setM2(IntModuleIncludingDoubleAndFloat(1))
445       .setM1(StringModule("sam"))
446       .depComponent(object : DepComponent {})
447     builder.doubleModule(DoubleModule())
448 
449     // Don't set other modules -- make sure it works.
450     val component = builder.build()
451     assertThat(component.s()).isEqualTo("sam")
452     assertThat(component.i()).isEqualTo(1)
453     assertThat(component.d()).isEqualTo(4.2)
454     assertThat(component.f()).isEqualTo(5.5f)
455     assertThat(component.l()).isEqualTo(6L)
456   }
457 
458   @Test
subcomponents_interfacenull459   fun subcomponents_interface() {
460     val parent = DaggerBuilderTest_ParentComponent.create()
461     val builder1 = parent.childInterfaceBuilder()
462 
463     try {
464       builder1.build()
465       fail()
466     } catch (expected: IllegalStateException) {}
467 
468     builder1
469       .setM2(IntModuleIncludingDoubleAndFloat(1))
470       .setM1(StringModule("sam"))
471       .set(ByteModule(7.toByte()))
472     builder1.set(FloatModule())
473 
474     val child1 = builder1.build()
475     assertThat(child1.s()).isEqualTo("sam")
476     assertThat(child1.i()).isEqualTo(1)
477     assertThat(child1.d()).isEqualTo(4.2)
478     assertThat(child1.f()).isEqualTo(5.5f)
479     assertThat(child1.l()).isEqualTo(6L)
480     assertThat(child1.b()).isEqualTo(7.toByte())
481   }
482 
483   @Test
subcomponents_abstractclassnull484   fun subcomponents_abstractclass() {
485     val parent = DaggerBuilderTest_ParentComponent.create()
486     val builder2 = parent.childAbstractClassBuilder()
487 
488     try {
489       builder2.build()
490       fail()
491     } catch (expected: IllegalStateException) {}
492 
493     builder2
494       .setM2(IntModuleIncludingDoubleAndFloat(10))
495       .setM1(StringModule("tara"))
496       .set(ByteModule(70.toByte()))
497     builder2.set(FloatModule())
498 
499     val child2 = builder2.build()
500     assertThat(child2.s()).isEqualTo("tara")
501     assertThat(child2.i()).isEqualTo(10)
502     assertThat(child2.d()).isEqualTo(4.2)
503     assertThat(child2.f()).isEqualTo(5.5f)
504     assertThat(child2.l()).isEqualTo(6L)
505     assertThat(child2.b()).isEqualTo(70.toByte())
506   }
507 
508   @Test
grandchildrennull509   fun grandchildren() {
510     val parent = DaggerBuilderTest_ParentComponent.create()
511     val middle1 = parent.middleBuilder().set(StringModule("sam")).build()
512     val grandchild1 = middle1.grandchildBuilder().set(IntModuleIncludingDoubleAndFloat(21)).build()
513     val grandchild2 = middle1.grandchildBuilder().set(IntModuleIncludingDoubleAndFloat(22)).build()
514     assertThat(middle1.s()).isEqualTo("sam")
515     assertThat(grandchild1.i()).isEqualTo(21)
516     assertThat(grandchild1.s()).isEqualTo("sam")
517     assertThat(grandchild2.i()).isEqualTo(22)
518     assertThat(grandchild2.s()).isEqualTo("sam")
519 
520     // Make sure grandchildren from newer children have no relation to the older ones.
521     val middle2 = parent.middleBuilder().set(StringModule("tara")).build()
522     val grandchild3 = middle2.grandchildBuilder().set(IntModuleIncludingDoubleAndFloat(23)).build()
523     val grandchild4 = middle2.grandchildBuilder().set(IntModuleIncludingDoubleAndFloat(24)).build()
524     assertThat(middle2.s()).isEqualTo("tara")
525     assertThat(grandchild3.i()).isEqualTo(23)
526     assertThat(grandchild3.s()).isEqualTo("tara")
527     assertThat(grandchild4.i()).isEqualTo(24)
528     assertThat(grandchild4.s()).isEqualTo("tara")
529   }
530 
531   @Test
diamondGrandchildrennull532   fun diamondGrandchildren() {
533     val parent = DaggerBuilderTest_ParentComponent.create()
534     val middle = parent.middleBuilder().set(StringModule("sam")).build()
535     val other = parent.otherBuilder().set(StringModule("tara")).build()
536     val middlegrand = middle.grandchildBuilder().set(IntModuleIncludingDoubleAndFloat(21)).build()
537     val othergrand = other.grandchildBuilder().set(IntModuleIncludingDoubleAndFloat(22)).build()
538     assertThat(middle.s()).isEqualTo("sam")
539     assertThat(other.s()).isEqualTo("tara")
540     assertThat(middlegrand.s()).isEqualTo("sam")
541     assertThat(othergrand.s()).isEqualTo("tara")
542     assertThat(middlegrand.i()).isEqualTo(21)
543     assertThat(othergrand.i()).isEqualTo(22)
544   }
545 
546   @Test
genericSubcomponentMethodnull547   fun genericSubcomponentMethod() {
548     val parent =
549       DaggerBuilderTest_ParentOfGenericComponent.builder().stringModule(StringModule("sam")).build()
550     val builder = parent.subcomponentBuilder()
551     val child = builder.set(IntModuleIncludingDoubleAndFloat(21)).build()
552     assertThat(child.s()).isEqualTo("sam")
553     assertThat(child.i()).isEqualTo(21)
554   }
555 
556   @Test
requireSubcomponentBuilderProvidersnull557   fun requireSubcomponentBuilderProviders() {
558     val parent = DaggerBuilderTest_ParentComponent.create()
559     val middle =
560       parent
561         .requiresMiddleChildBuilder()
562         .subcomponentBuilderProvider()
563         .get()
564         .set(StringModule("sam"))
565         .build()
566     val grandchild =
567       middle
568         .requiresGrandchildBuilder()
569         .subcomponentBuilderProvider()
570         .get()
571         .set(IntModuleIncludingDoubleAndFloat(12))
572         .build()
573     assertThat(middle.s()).isEqualTo("sam")
574     assertThat(grandchild.i()).isEqualTo(12)
575     assertThat(grandchild.s()).isEqualTo("sam")
576   }
577 
578   @Test
requireSubcomponentBuildersnull579   fun requireSubcomponentBuilders() {
580     val parent = DaggerBuilderTest_ParentComponent.create()
581     val middle =
582       parent.requiresMiddleChildBuilder().subcomponentBuilder().set(StringModule("sam")).build()
583     val grandchild =
584       middle
585         .requiresGrandchildBuilder()
586         .subcomponentBuilder()
587         .set(IntModuleIncludingDoubleAndFloat(12))
588         .build()
589     assertThat(middle.s()).isEqualTo("sam")
590     assertThat(grandchild.i()).isEqualTo(12)
591     assertThat(grandchild.s()).isEqualTo("sam")
592   }
593 }
594