1 /* 2 * Copyright (C) 2023 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.assisted 18 19 import com.google.common.truth.Truth.assertThat 20 import dagger.Component 21 import dagger.assisted.Assisted 22 import dagger.assisted.AssistedFactory 23 import dagger.assisted.AssistedInject 24 import javax.inject.Inject 25 import javax.inject.Provider 26 import javax.inject.Singleton 27 import org.junit.Test 28 import org.junit.runner.RunWith 29 import org.junit.runners.JUnit4 30 31 @RunWith(JUnit4::class) 32 internal class AssistedFactoryParameterizedTest { 33 @Singleton 34 @Component 35 interface ParentComponent { 36 // Tests a parameterized Factory with unique @Assisted types uniqueParameterizedFooFactorynull37 fun uniqueParameterizedFooFactory(): ParameterizedFooFactory<Dep2, AssistedDep2> 38 39 // Tests a parameterized Factory with duplicate @Assisted types in its resolved request type. 40 // Note: this is fine since the @Assisted types are still unique on the @AssistedInject and 41 // @AssistedFactory types, so that the generated code can correctly matches types. 42 fun dupeParameterizedFooFactory(): ParameterizedFooFactory<Dep1, AssistedDep1> 43 44 // Tests a parameterized Factory with same type as binding 45 fun bindingParameterizedFooFactory(): ParameterizedFooFactory<Dep1, Dep1> 46 47 // Tests a parameterized Factory with fixed type parameters 48 fun fixedParameterizedFooFactory(): FixedParameterizedFooFactory 49 50 // Tests a parameterized Factory that extends an interface with a parameterized return type 51 fun extendedParameterizedFooFactory(): ExtendedFooFactory<Dep2, AssistedDep2> 52 53 // Tests a request of factories from another binding. 54 fun someEntryPoint(): SomeEntryPoint 55 } 56 57 class Dep1 @Inject constructor( 58 @Suppress("UNUSED_PARAMETER") dep2: Dep2, @Suppress("UNUSED_PARAMETER") dep3: Dep3) 59 class Dep2 @Inject constructor(@Suppress("UNUSED_PARAMETER") dep3: Dep3) 60 class Dep3 @Inject constructor(@Suppress("UNUSED_PARAMETER") dep4: Dep4) 61 class Dep4 @Inject constructor() 62 63 // A base interface to test that factories can reference subclasses of the assisted parameter. 64 interface AssistedDep 65 class AssistedDep1 : AssistedDep 66 class AssistedDep2 : AssistedDep 67 abstract class BaseFoo { 68 @Inject lateinit var dep4: Dep4 69 } 70 71 class ParameterizedFoo<DepT, AssistedDepT> 72 @AssistedInject 73 constructor( 74 val dep1: Dep1, 75 @Assisted val assistedDep1: AssistedDep1, 76 val depTProvider: Provider<DepT>, 77 @Assisted val assistedDepT: AssistedDepT, 78 @Assisted val assistedInt: Int, 79 val factory: ParameterizedFooFactory<DepT, AssistedDepT> 80 ) : BaseFoo() { 81 @Inject lateinit var dep3: Dep3 82 } 83 84 @AssistedFactory 85 interface ParameterizedFooFactory<DepT, AssistedDepT> { createnull86 fun create( 87 assistedDep1: AssistedDep1, 88 assistedDepT: AssistedDepT, 89 assistedInt: Int 90 ): ParameterizedFoo<DepT, AssistedDepT> 91 } 92 93 @Test 94 fun testUniqueParameterizedFooFactory() { 95 val assistedDep1 = AssistedDep1() 96 val assistedDep2 = AssistedDep2() 97 val assistedInt = 7 98 val parameterizedFoo = 99 DaggerAssistedFactoryParameterizedTest_ParentComponent.create() 100 .uniqueParameterizedFooFactory() 101 .create(assistedDep1, assistedDep2, assistedInt) 102 assertThat(parameterizedFoo.dep1).isNotNull() 103 assertThat(parameterizedFoo.depTProvider).isNotNull() 104 assertThat(parameterizedFoo.depTProvider.get()).isNotNull() 105 assertThat(parameterizedFoo.dep3).isNotNull() 106 assertThat(parameterizedFoo.dep4).isNotNull() 107 assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1) 108 assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep2) 109 assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt) 110 assertThat(parameterizedFoo.factory).isNotNull() 111 } 112 113 @Test testDupeParameterizedFooFactorynull114 fun testDupeParameterizedFooFactory() { 115 val assistedDep1 = AssistedDep1() 116 val assistedInt = 7 117 val parameterizedFoo = 118 DaggerAssistedFactoryParameterizedTest_ParentComponent.create() 119 .dupeParameterizedFooFactory() 120 .create(assistedDep1, assistedDep1, assistedInt) 121 assertThat(parameterizedFoo.dep1).isNotNull() 122 assertThat(parameterizedFoo.depTProvider).isNotNull() 123 assertThat(parameterizedFoo.depTProvider.get()).isNotNull() 124 assertThat(parameterizedFoo.dep3).isNotNull() 125 assertThat(parameterizedFoo.dep4).isNotNull() 126 assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1) 127 assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep1) 128 assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt) 129 assertThat(parameterizedFoo.factory).isNotNull() 130 } 131 132 @Test testBindingParameterizedFooFactorynull133 fun testBindingParameterizedFooFactory() { 134 val assistedDep1 = AssistedDep1() 135 val dep1 = Dep1(Dep2(Dep3(Dep4())), Dep3(Dep4())) 136 val assistedInt = 7 137 val parameterizedFoo = 138 DaggerAssistedFactoryParameterizedTest_ParentComponent.create() 139 .bindingParameterizedFooFactory() 140 .create(assistedDep1, dep1, assistedInt) 141 assertThat(parameterizedFoo.dep1).isNotNull() 142 assertThat(parameterizedFoo.depTProvider).isNotNull() 143 assertThat(parameterizedFoo.depTProvider.get()).isNotNull() 144 assertThat(parameterizedFoo.dep3).isNotNull() 145 assertThat(parameterizedFoo.dep4).isNotNull() 146 assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1) 147 assertThat(parameterizedFoo.assistedDepT).isEqualTo(dep1) 148 assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt) 149 assertThat(parameterizedFoo.factory).isNotNull() 150 } 151 152 @AssistedFactory 153 interface FixedParameterizedFooFactory { createnull154 fun create( 155 assistedDep1: AssistedDep1, 156 assistedDep2: AssistedDep2, 157 assistedInt: Int 158 ): ParameterizedFoo<Dep2, AssistedDep2> 159 } 160 161 @Test 162 fun testFixedParameterizedFooFactory() { 163 val assistedDep1 = AssistedDep1() 164 val assistedDep2 = AssistedDep2() 165 val assistedInt = 7 166 val parameterizedFoo = 167 DaggerAssistedFactoryParameterizedTest_ParentComponent.create() 168 .fixedParameterizedFooFactory() 169 .create(assistedDep1, assistedDep2, assistedInt) 170 assertThat(parameterizedFoo.dep1).isNotNull() 171 assertThat(parameterizedFoo.depTProvider).isNotNull() 172 assertThat(parameterizedFoo.depTProvider.get()).isNotNull() 173 assertThat(parameterizedFoo.dep3).isNotNull() 174 assertThat(parameterizedFoo.dep4).isNotNull() 175 assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1) 176 assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep2) 177 assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt) 178 assertThat(parameterizedFoo.factory).isNotNull() 179 } 180 181 interface ParameterizedFactory<ReturnT, DepT, AssistedDepT> { 182 // Use different parameter names than Foo to make sure we're not assuming they're the same. createnull183 fun create( 184 factoryAssistedDep1: AssistedDep1, 185 factoryAssistedDepT: AssistedDepT, 186 factoryAssistedInt: Int 187 ): ReturnT 188 } 189 190 @AssistedFactory 191 interface ExtendedFooFactory<DepT, AssistedDepT> : 192 ParameterizedFactory<ParameterizedFoo<DepT, AssistedDepT>, DepT, AssistedDepT> 193 194 @Test 195 fun testExtendedFooFactory() { 196 val assistedDep1 = AssistedDep1() 197 val assistedDep2 = AssistedDep2() 198 val assistedInt = 7 199 val parameterizedFoo = 200 DaggerAssistedFactoryParameterizedTest_ParentComponent.create() 201 .extendedParameterizedFooFactory() 202 .create(assistedDep1, assistedDep2, assistedInt) 203 assertThat(parameterizedFoo.dep1).isNotNull() 204 assertThat(parameterizedFoo.depTProvider).isNotNull() 205 assertThat(parameterizedFoo.depTProvider.get()).isNotNull() 206 assertThat(parameterizedFoo.dep3).isNotNull() 207 assertThat(parameterizedFoo.dep4).isNotNull() 208 assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1) 209 assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep2) 210 assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt) 211 assertThat(parameterizedFoo.factory).isNotNull() 212 } 213 214 class SomeEntryPoint 215 @Inject 216 constructor(val dupeParameterizedFooFactory: ParameterizedFooFactory<Dep1, AssistedDep1>) 217 218 @Test testParameterizedFooFactoryFromSomeEntryPointnull219 fun testParameterizedFooFactoryFromSomeEntryPoint() { 220 val assistedDep1 = AssistedDep1() 221 val assistedInt = 7 222 val parameterizedFoo = 223 DaggerAssistedFactoryParameterizedTest_ParentComponent.create() 224 .someEntryPoint() 225 .dupeParameterizedFooFactory 226 .create(assistedDep1, assistedDep1, assistedInt) 227 assertThat(parameterizedFoo.dep1).isNotNull() 228 assertThat(parameterizedFoo.depTProvider).isNotNull() 229 assertThat(parameterizedFoo.depTProvider.get()).isNotNull() 230 assertThat(parameterizedFoo.dep3).isNotNull() 231 assertThat(parameterizedFoo.dep4).isNotNull() 232 assertThat(parameterizedFoo.assistedDep1).isEqualTo(assistedDep1) 233 assertThat(parameterizedFoo.assistedDepT).isEqualTo(assistedDep1) 234 assertThat(parameterizedFoo.assistedInt).isEqualTo(assistedInt) 235 assertThat(parameterizedFoo.factory).isNotNull() 236 } 237 } 238