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