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