1 /* 2 * Copyright (C) 2014 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.internal.codegen; 18 19 import androidx.room.compiler.processing.util.Source; 20 import com.google.common.collect.ImmutableList; 21 import dagger.testing.compile.CompilerTests; 22 import dagger.testing.golden.GoldenFileRule; 23 import org.junit.Rule; 24 import org.junit.Test; 25 import org.junit.runner.RunWith; 26 import org.junit.runners.Parameterized; 27 import org.junit.runners.Parameterized.Parameters; 28 29 @RunWith(Parameterized.class) 30 public class SwitchingProviderTest { 31 @Parameters(name = "{0}") parameters()32 public static ImmutableList<Object[]> parameters() { 33 return CompilerMode.TEST_PARAMETERS; 34 } 35 36 @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule(); 37 38 private final CompilerMode compilerMode; 39 SwitchingProviderTest(CompilerMode compilerMode)40 public SwitchingProviderTest(CompilerMode compilerMode) { 41 this.compilerMode = compilerMode; 42 } 43 44 @Test switchingProviderTest()45 public void switchingProviderTest() throws Exception { 46 ImmutableList.Builder<Source> sources = ImmutableList.builder(); 47 StringBuilder entryPoints = new StringBuilder(); 48 for (int i = 0; i <= 100; i++) { 49 String bindingName = "Binding" + i; 50 sources.add( 51 CompilerTests.javaSource( 52 "test." + bindingName, 53 "package test;", 54 "", 55 "import javax.inject.Inject;", 56 "", 57 "final class " + bindingName + " {", 58 " @Inject", 59 " " + bindingName + "() {}", 60 "}")); 61 entryPoints.append(String.format(" Provider<%1$s> get%1$sProvider();\n", bindingName)); 62 } 63 64 sources.add( 65 CompilerTests.javaSource( 66 "test.TestComponent", 67 "package test;", 68 "", 69 "import dagger.Component;", 70 "import javax.inject.Provider;", 71 "", 72 "@Component", 73 "interface TestComponent {", 74 entryPoints.toString(), 75 "}")); 76 77 CompilerTests.daggerCompiler(sources.build()) 78 .withProcessingOptions(compilerMode.processorOptions()) 79 .compile( 80 subject -> { 81 subject.hasErrorCount(0); 82 subject.hasWarningCount(0); 83 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 84 }); 85 } 86 87 @Test unscopedBinds()88 public void unscopedBinds() throws Exception { 89 Source module = 90 CompilerTests.javaSource( 91 "test.TestModule", 92 "package test;", 93 "", 94 "import dagger.Binds;", 95 "import dagger.Module;", 96 "import dagger.Provides;", 97 "", 98 "@Module", 99 "interface TestModule {", 100 " @Provides", 101 " static String s() {", 102 " return new String();", 103 " }", 104 "", 105 " @Binds CharSequence c(String s);", 106 " @Binds Object o(CharSequence c);", 107 "}"); 108 Source component = 109 CompilerTests.javaSource( 110 "test.TestComponent", 111 "package test;", 112 "", 113 "import dagger.Component;", 114 "import javax.inject.Provider;", 115 "", 116 "@Component(modules = TestModule.class)", 117 "interface TestComponent {", 118 " Provider<Object> objectProvider();", 119 " Provider<CharSequence> charSequenceProvider();", 120 "}"); 121 122 CompilerTests.daggerCompiler(module, component) 123 .withProcessingOptions(compilerMode.processorOptions()) 124 .compile( 125 subject -> { 126 subject.hasErrorCount(0); 127 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 128 }); 129 } 130 131 @Test scopedBinds()132 public void scopedBinds() throws Exception { 133 Source module = 134 CompilerTests.javaSource( 135 "test.TestModule", 136 "package test;", 137 "", 138 "import dagger.Binds;", 139 "import dagger.Module;", 140 "import dagger.Provides;", 141 "import javax.inject.Singleton;", 142 "", 143 "@Module", 144 "interface TestModule {", 145 " @Provides", 146 " static String s() {", 147 " return new String();", 148 " }", 149 "", 150 " @Binds @Singleton Object o(CharSequence s);", 151 " @Binds @Singleton CharSequence c(String s);", 152 "}"); 153 Source component = 154 CompilerTests.javaSource( 155 "test.TestComponent", 156 "package test;", 157 "", 158 "import dagger.Component;", 159 "import javax.inject.Provider;", 160 "import javax.inject.Singleton;", 161 "", 162 "@Singleton", 163 "@Component(modules = TestModule.class)", 164 "interface TestComponent {", 165 " Provider<Object> objectProvider();", 166 " Provider<CharSequence> charSequenceProvider();", 167 "}"); 168 169 CompilerTests.daggerCompiler(module, component) 170 .withProcessingOptions(compilerMode.processorOptions()) 171 .compile( 172 subject -> { 173 subject.hasErrorCount(0); 174 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 175 }); 176 } 177 178 @Test emptyMultibindings_avoidSwitchProviders()179 public void emptyMultibindings_avoidSwitchProviders() throws Exception { 180 Source module = 181 CompilerTests.javaSource( 182 "test.TestModule", 183 "package test;", 184 "", 185 "import dagger.multibindings.Multibinds;", 186 "import dagger.Module;", 187 "import java.util.Map;", 188 "import java.util.Set;", 189 "", 190 "@Module", 191 "interface TestModule {", 192 " @Multibinds Set<String> set();", 193 " @Multibinds Map<String, String> map();", 194 "}"); 195 Source component = 196 CompilerTests.javaSource( 197 "test.TestComponent", 198 "package test;", 199 "", 200 "import dagger.Component;", 201 "import java.util.Map;", 202 "import java.util.Set;", 203 "import javax.inject.Provider;", 204 "", 205 "@Component(modules = TestModule.class)", 206 "interface TestComponent {", 207 " Provider<Set<String>> setProvider();", 208 " Provider<Map<String, String>> mapProvider();", 209 "}"); 210 211 CompilerTests.daggerCompiler(module, component) 212 .withProcessingOptions(compilerMode.processorOptions()) 213 .compile( 214 subject -> { 215 subject.hasErrorCount(0); 216 subject.hasWarningCount(0); 217 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 218 }); 219 } 220 221 @Test memberInjectors()222 public void memberInjectors() throws Exception { 223 Source foo = 224 CompilerTests.javaSource( 225 "test.Foo", 226 "package test;", 227 "", 228 "class Foo {}"); 229 Source component = 230 CompilerTests.javaSource( 231 "test.TestComponent", 232 "package test;", 233 "", 234 "import dagger.Component;", 235 "import dagger.MembersInjector;", 236 "import javax.inject.Provider;", 237 "", 238 "@Component", 239 "interface TestComponent {", 240 " Provider<MembersInjector<Foo>> providerOfMembersInjector();", 241 "}"); 242 243 CompilerTests.daggerCompiler(foo, component) 244 .withProcessingOptions(compilerMode.processorOptions()) 245 .compile( 246 subject -> { 247 subject.hasErrorCount(0); 248 subject.hasWarningCount(0); 249 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 250 }); 251 } 252 253 @Test optionals()254 public void optionals() throws Exception { 255 Source present = 256 CompilerTests.javaSource( 257 "test.Present", 258 "package test;", 259 "", 260 "class Present {}"); 261 Source absent = 262 CompilerTests.javaSource( 263 "test.Absent", 264 "package test;", 265 "", 266 "class Absent {}"); 267 Source module = 268 CompilerTests.javaSource( 269 "test.TestModule", 270 "package test;", 271 "", 272 "import dagger.BindsOptionalOf;", 273 "import dagger.Module;", 274 "import dagger.Provides;", 275 "", 276 "@Module", 277 "interface TestModule {", 278 " @BindsOptionalOf Present bindOptionalOfPresent();", 279 " @BindsOptionalOf Absent bindOptionalOfAbsent();", 280 "", 281 " @Provides static Present p() { return new Present(); }", 282 "}"); 283 Source component = 284 CompilerTests.javaSource( 285 "test.TestComponent", 286 "package test;", 287 "", 288 "import dagger.Component;", 289 "import java.util.Optional;", 290 "import javax.inject.Provider;", 291 "", 292 "@Component(modules = TestModule.class)", 293 "interface TestComponent {", 294 " Provider<Optional<Present>> providerOfOptionalOfPresent();", 295 " Provider<Optional<Absent>> providerOfOptionalOfAbsent();", 296 "}"); 297 298 CompilerTests.daggerCompiler(present, absent, module, component) 299 .withProcessingOptions(compilerMode.processorOptions()) 300 .compile( 301 subject -> { 302 subject.hasErrorCount(0); 303 subject.hasWarningCount(0); 304 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 305 }); 306 } 307 } 308