1 /* 2 * Copyright (C) 2021 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 import static java.lang.annotation.RetentionPolicy.RUNTIME; 21 22 import dagger.Binds; 23 import dagger.BindsInstance; 24 import dagger.BindsOptionalOf; 25 import dagger.Component; 26 import dagger.Module; 27 import dagger.Provides; 28 import dagger.assisted.AssistedFactory; 29 import dagger.assisted.AssistedInject; 30 import dagger.multibindings.IntoSet; 31 import dagger.multibindings.Multibinds; 32 import java.lang.annotation.Retention; 33 import java.util.Optional; 34 import java.util.Set; 35 import javax.inject.Inject; 36 import javax.inject.Qualifier; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 import org.junit.runners.JUnit4; 40 41 /** Tests that qualified assisted types can be provided and injected as normal types. */ 42 @RunWith(JUnit4.class) 43 public final class AssistedFactoryAsQualifiedBindingTest { 44 45 @Qualifier 46 @Retention(RUNTIME) 47 @interface AsComponentDependency {} 48 49 @Qualifier 50 @Retention(RUNTIME) 51 @interface AsProvides {} 52 53 @Qualifier 54 @Retention(RUNTIME) 55 @interface AsBinds {} 56 57 @Qualifier 58 @Retention(RUNTIME) 59 @interface AsOptional {} 60 61 @Qualifier 62 @Retention(RUNTIME) 63 @interface AsMultibinding {} 64 65 @Component(modules = BarFactoryModule.class) 66 interface TestComponent { foo()67 Foo foo(); 68 69 @Component.Factory 70 interface Factory { create( @indsInstance @sComponentDependency Bar bar, @BindsInstance @AsComponentDependency BarFactory barFactory)71 TestComponent create( 72 @BindsInstance @AsComponentDependency Bar bar, 73 @BindsInstance @AsComponentDependency BarFactory barFactory); 74 } 75 } 76 77 @Module 78 interface BarFactoryModule { 79 80 @Provides 81 @AsProvides providesBar(@sComponentDependency Bar bar)82 static Bar providesBar(@AsComponentDependency Bar bar) { 83 return bar; 84 } 85 86 @Provides 87 @AsProvides providesBarFactory(@sComponentDependency BarFactory barFactory)88 static BarFactory providesBarFactory(@AsComponentDependency BarFactory barFactory) { 89 return barFactory; 90 } 91 92 @Binds 93 @AsBinds bindsBar(@sComponentDependency Bar bar)94 Bar bindsBar(@AsComponentDependency Bar bar); 95 96 @Binds 97 @AsBinds bindsBarFactory(@sComponentDependency BarFactory barFactory)98 BarFactory bindsBarFactory(@AsComponentDependency BarFactory barFactory); 99 100 @BindsOptionalOf 101 @AsOptional optionalBar()102 Bar optionalBar(); 103 104 @BindsOptionalOf 105 @AsOptional optionalBarFactory()106 BarFactory optionalBarFactory(); 107 108 @Provides 109 @AsOptional providesOptionalBar(@sComponentDependency Bar bar)110 static Bar providesOptionalBar(@AsComponentDependency Bar bar) { 111 return bar; 112 } 113 114 @Provides 115 @AsOptional providesOptionalBarFactory(@sComponentDependency BarFactory barFactory)116 static BarFactory providesOptionalBarFactory(@AsComponentDependency BarFactory barFactory) { 117 return barFactory; 118 } 119 120 @Multibinds 121 @AsMultibinding barSet()122 Set<Bar> barSet(); 123 124 @Multibinds 125 @AsMultibinding barFactorySet()126 Set<BarFactory> barFactorySet(); 127 128 @Provides 129 @IntoSet 130 @AsMultibinding providesMultibindingBar(@sComponentDependency Bar bar)131 static Bar providesMultibindingBar(@AsComponentDependency Bar bar) { 132 return bar; 133 } 134 135 @Provides 136 @IntoSet 137 @AsMultibinding providesMultibindingBarFactory(@sComponentDependency BarFactory barFactory)138 static BarFactory providesMultibindingBarFactory(@AsComponentDependency BarFactory barFactory) { 139 return barFactory; 140 } 141 142 @Multibinds unqualifiedBarSet()143 Set<Bar> unqualifiedBarSet(); 144 145 @Multibinds unqualifiedBarFactorySet()146 Set<BarFactory> unqualifiedBarFactorySet(); 147 148 @Provides 149 @IntoSet providesUnqualifiedMultibindingBar(@sComponentDependency Bar bar)150 static Bar providesUnqualifiedMultibindingBar(@AsComponentDependency Bar bar) { 151 return bar; 152 } 153 154 @Provides 155 @IntoSet providesUnqualifiedMultibindingBarFactory( @sComponentDependency BarFactory barFactory)156 static BarFactory providesUnqualifiedMultibindingBarFactory( 157 @AsComponentDependency BarFactory barFactory) { 158 return barFactory; 159 } 160 } 161 162 static class Foo { 163 private final BarFactory barFactory; 164 private final Bar barAsComponentDependency; 165 private final BarFactory barFactoryAsComponentDependency; 166 private final Bar barAsProvides; 167 private final BarFactory barFactoryAsProvides; 168 private final Bar barAsBinds; 169 private final BarFactory barFactoryAsBinds; 170 private final Optional<Bar> optionalBar; 171 private final Optional<BarFactory> optionalBarFactory; 172 private final Set<Bar> barSet; 173 private final Set<BarFactory> barFactorySet; 174 private final Set<Bar> unqualifiedBarSet; 175 private final Set<BarFactory> unqualifiedBarFactorySet; 176 177 @Inject Foo( BarFactory barFactory, @AsComponentDependency Bar barAsComponentDependency, @AsComponentDependency BarFactory barFactoryAsComponentDependency, @AsProvides Bar barAsProvides, @AsProvides BarFactory barFactoryAsProvides, @AsBinds Bar barAsBinds, @AsBinds BarFactory barFactoryAsBinds, @AsOptional Optional<Bar> optionalBar, @AsOptional Optional<BarFactory> optionalBarFactory, @AsMultibinding Set<Bar> barSet, @AsMultibinding Set<BarFactory> barFactorySet, Set<Bar> unqualifiedBarSet, Set<BarFactory> unqualifiedBarFactorySet)178 Foo( 179 BarFactory barFactory, 180 @AsComponentDependency Bar barAsComponentDependency, 181 @AsComponentDependency BarFactory barFactoryAsComponentDependency, 182 @AsProvides Bar barAsProvides, 183 @AsProvides BarFactory barFactoryAsProvides, 184 @AsBinds Bar barAsBinds, 185 @AsBinds BarFactory barFactoryAsBinds, 186 @AsOptional Optional<Bar> optionalBar, 187 @AsOptional Optional<BarFactory> optionalBarFactory, 188 @AsMultibinding Set<Bar> barSet, 189 @AsMultibinding Set<BarFactory> barFactorySet, 190 Set<Bar> unqualifiedBarSet, 191 Set<BarFactory> unqualifiedBarFactorySet) { 192 this.barFactory = barFactory; 193 this.barAsComponentDependency = barAsComponentDependency; 194 this.barFactoryAsComponentDependency = barFactoryAsComponentDependency; 195 this.barAsProvides = barAsProvides; 196 this.barFactoryAsProvides = barFactoryAsProvides; 197 this.barAsBinds = barAsBinds; 198 this.barFactoryAsBinds = barFactoryAsBinds; 199 this.optionalBar = optionalBar; 200 this.optionalBarFactory = optionalBarFactory; 201 this.barSet = barSet; 202 this.barFactorySet = barFactorySet; 203 this.unqualifiedBarSet = unqualifiedBarSet; 204 this.unqualifiedBarFactorySet = unqualifiedBarFactorySet; 205 } 206 } 207 208 static class Bar { 209 @AssistedInject Bar()210 Bar() {} 211 } 212 213 @AssistedFactory 214 interface BarFactory { create()215 Bar create(); 216 } 217 218 @Test testFoo()219 public void testFoo() { 220 Bar bar = new Bar(); 221 BarFactory barFactory = () -> bar; 222 Foo foo = 223 DaggerAssistedFactoryAsQualifiedBindingTest_TestComponent.factory() 224 .create(bar, barFactory) 225 .foo(); 226 227 // Test we can inject the "real" BarFactory implemented by Dagger 228 assertThat(foo.barFactory).isNotNull(); 229 assertThat(foo.barFactory).isNotEqualTo(barFactory); 230 assertThat(foo.barFactory.create()).isNotEqualTo(bar); 231 232 // Test injection of a qualified Bar/BarFactory with custom @BindsInstance implementation 233 assertThat(foo.barAsComponentDependency).isEqualTo(bar); 234 assertThat(foo.barFactoryAsComponentDependency).isEqualTo(barFactory); 235 236 // Test injection of a qualified Bar/BarFactory with custom @Provides implementation 237 assertThat(foo.barAsProvides).isEqualTo(bar); 238 assertThat(foo.barFactoryAsProvides).isEqualTo(barFactory); 239 240 // Test injection of a qualified Bar/BarFactory with custom @Binds implementation 241 assertThat(foo.barAsBinds).isEqualTo(bar); 242 assertThat(foo.barFactoryAsBinds).isEqualTo(barFactory); 243 244 // Test injection of a qualified Bar/BarFactory with custom @BindsOptionalOf implementation 245 assertThat(foo.optionalBar).isPresent(); 246 assertThat(foo.optionalBar).hasValue(bar); 247 assertThat(foo.optionalBarFactory).isPresent(); 248 assertThat(foo.optionalBarFactory).hasValue(barFactory); 249 250 // Test injection of a qualified Bar/BarFactory as multibinding 251 assertThat(foo.barSet).containsExactly(bar); 252 assertThat(foo.barFactorySet).containsExactly(barFactory); 253 254 // Test injection of a unqualified Bar/BarFactory as multibinding 255 assertThat(foo.unqualifiedBarSet).containsExactly(bar); 256 assertThat(foo.unqualifiedBarFactorySet).containsExactly(barFactory); 257 } 258 } 259