1 /* 2 * Copyright (C) 2017 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 static com.google.testing.compile.CompilationSubject.assertThat; 20 import static dagger.internal.codegen.Compilers.compilerWithOptions; 21 22 import com.google.testing.compile.Compilation; 23 import com.google.testing.compile.JavaFileObjects; 24 import java.util.Collection; 25 import javax.tools.JavaFileObject; 26 import org.junit.Test; 27 import org.junit.runner.RunWith; 28 import org.junit.runners.Parameterized; 29 import org.junit.runners.Parameterized.Parameters; 30 31 @RunWith(Parameterized.class) 32 public class SetBindingRequestFulfillmentWithGuavaTest { 33 @Parameters(name = "{0}") parameters()34 public static Collection<Object[]> parameters() { 35 return CompilerMode.TEST_PARAMETERS; 36 } 37 38 private final CompilerMode compilerMode; 39 SetBindingRequestFulfillmentWithGuavaTest(CompilerMode compilerMode)40 public SetBindingRequestFulfillmentWithGuavaTest(CompilerMode compilerMode) { 41 this.compilerMode = compilerMode; 42 } 43 44 @Test setBindings()45 public void setBindings() { 46 JavaFileObject emptySetModuleFile = JavaFileObjects.forSourceLines("test.EmptySetModule", 47 "package test;", 48 "", 49 "import dagger.Module;", 50 "import dagger.Provides;", 51 "import dagger.multibindings.ElementsIntoSet;", 52 "import dagger.multibindings.Multibinds;", 53 "import java.util.Collections;", 54 "import java.util.Set;", 55 "", 56 "@Module", 57 "abstract class EmptySetModule {", 58 " @Multibinds abstract Set<Object> objects();", 59 "", 60 " @Provides @ElementsIntoSet", 61 " static Set<String> emptySet() { ", 62 " return Collections.emptySet();", 63 " }", 64 " @Provides @ElementsIntoSet", 65 " static Set<Integer> onlyContributionIsElementsIntoSet() { ", 66 " return Collections.emptySet();", 67 " }", 68 "}"); 69 JavaFileObject setModuleFile = JavaFileObjects.forSourceLines("test.SetModule", 70 "package test;", 71 "", 72 "import dagger.Module;", 73 "import dagger.Provides;", 74 "import dagger.multibindings.IntoSet;", 75 "", 76 "@Module", 77 "final class SetModule {", 78 " @Provides @IntoSet static String string() { return \"\"; }", 79 "}"); 80 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 81 "package test;", 82 "", 83 "import dagger.Component;", 84 "import java.util.Set;", 85 "import javax.inject.Provider;", 86 "", 87 "@Component(modules = {EmptySetModule.class, SetModule.class})", 88 "interface TestComponent {", 89 " Set<String> strings();", 90 " Set<Object> objects();", 91 " Set<Integer> onlyContributionIsElementsIntoSet();", 92 "}"); 93 JavaFileObject generatedComponent = 94 JavaFileObjects.forSourceLines( 95 "test.DaggerTestComponent", 96 "package test;", 97 "", 98 "import com.google.common.collect.ImmutableSet;", 99 "", 100 GeneratedLines.generatedAnnotations(), 101 "final class DaggerTestComponent implements TestComponent {", 102 " @Override", 103 " public Set<String> strings() {", 104 " return ImmutableSet.<String>builderWithExpectedSize(2)", 105 " .addAll(EmptySetModule_EmptySetFactory.emptySet())", 106 " .add(SetModule_StringFactory.string())", 107 " .build();", 108 " }", 109 "", 110 " @Override", 111 " public Set<Object> objects() {", 112 " return ImmutableSet.<Object>of();", 113 " }", 114 "", 115 " @Override", 116 " public Set<Integer> onlyContributionIsElementsIntoSet() {", 117 " return ImmutableSet.<Integer>copyOf(", 118 " EmptySetModule_OnlyContributionIsElementsIntoSetFactory", 119 " .onlyContributionIsElementsIntoSet());", 120 " }", 121 "}"); 122 Compilation compilation = 123 compilerWithOptions(compilerMode.javacopts()) 124 .compile(emptySetModuleFile, setModuleFile, componentFile); 125 assertThat(compilation).succeeded(); 126 assertThat(compilation) 127 .generatedSourceFile("test.DaggerTestComponent") 128 .containsElementsIn(generatedComponent); 129 } 130 131 @Test inaccessible()132 public void inaccessible() { 133 JavaFileObject inaccessible = 134 JavaFileObjects.forSourceLines( 135 "other.Inaccessible", 136 "package other;", 137 "", 138 "class Inaccessible {}"); 139 JavaFileObject inaccessible2 = 140 JavaFileObjects.forSourceLines( 141 "other.Inaccessible2", 142 "package other;", 143 "", 144 "class Inaccessible2 {}"); 145 JavaFileObject usesInaccessible = 146 JavaFileObjects.forSourceLines( 147 "other.UsesInaccessible", 148 "package other;", 149 "", 150 "import java.util.Set;", 151 "import javax.inject.Inject;", 152 "", 153 "public class UsesInaccessible {", 154 " @Inject UsesInaccessible(Set<Inaccessible> set1, Set<Inaccessible2> set2) {}", 155 "}"); 156 157 JavaFileObject module = 158 JavaFileObjects.forSourceLines( 159 "other.TestModule", 160 "package other;", 161 "", 162 "import dagger.Module;", 163 "import dagger.Provides;", 164 "import dagger.multibindings.ElementsIntoSet;", 165 "import dagger.multibindings.Multibinds;", 166 "import java.util.Collections;", 167 "import java.util.Set;", 168 "", 169 "@Module", 170 "public abstract class TestModule {", 171 " @Multibinds abstract Set<Inaccessible> objects();", 172 "", 173 " @Provides @ElementsIntoSet", 174 " static Set<Inaccessible2> emptySet() { ", 175 " return Collections.emptySet();", 176 " }", 177 "}"); 178 JavaFileObject componentFile = 179 JavaFileObjects.forSourceLines( 180 "test.TestComponent", 181 "package test;", 182 "", 183 "import dagger.Component;", 184 "import java.util.Set;", 185 "import javax.inject.Provider;", 186 "import other.TestModule;", 187 "import other.UsesInaccessible;", 188 "", 189 "@Component(modules = TestModule.class)", 190 "interface TestComponent {", 191 " UsesInaccessible usesInaccessible();", 192 "}"); 193 JavaFileObject generatedComponent = 194 JavaFileObjects.forSourceLines( 195 "test.DaggerTestComponent", 196 "package test;", 197 "", 198 "import com.google.common.collect.ImmutableSet;", 199 "import other.TestModule_EmptySetFactory;", 200 "import other.UsesInaccessible;", 201 "import other.UsesInaccessible_Factory;", 202 "", 203 GeneratedLines.generatedAnnotations(), 204 "final class DaggerTestComponent implements TestComponent {", 205 " private Set setOfInaccessible2() {", 206 " return ImmutableSet.copyOf(TestModule_EmptySetFactory.emptySet());", 207 " }", 208 "", 209 " @Override", 210 " public UsesInaccessible usesInaccessible() {", 211 " return UsesInaccessible_Factory.newInstance(", 212 " (Set) ImmutableSet.of(),", 213 " (Set) setOfInaccessible2());", 214 " }", 215 "}"); 216 Compilation compilation = 217 compilerWithOptions(compilerMode.javacopts()) 218 .compile(module, inaccessible, inaccessible2, usesInaccessible, componentFile); 219 assertThat(compilation).succeeded(); 220 assertThat(compilation) 221 .generatedSourceFile("test.DaggerTestComponent") 222 .containsElementsIn(generatedComponent); 223 } 224 225 @Test subcomponentOmitsInheritedBindings()226 public void subcomponentOmitsInheritedBindings() { 227 JavaFileObject parent = 228 JavaFileObjects.forSourceLines( 229 "test.Parent", 230 "package test;", 231 "", 232 "import dagger.Component;", 233 "", 234 "@Component(modules = ParentModule.class)", 235 "interface Parent {", 236 " Child child();", 237 "}"); 238 JavaFileObject parentModule = 239 JavaFileObjects.forSourceLines( 240 "test.ParentModule", 241 "package test;", 242 "", 243 "import dagger.Module;", 244 "import dagger.Provides;", 245 "import dagger.multibindings.IntoSet;", 246 "import dagger.multibindings.StringKey;", 247 "", 248 "@Module", 249 "class ParentModule {", 250 " @Provides @IntoSet static Object parentObject() {", 251 " return \"parent object\";", 252 " }", 253 "}"); 254 JavaFileObject child = 255 JavaFileObjects.forSourceLines( 256 "test.Child", 257 "package test;", 258 "", 259 "import dagger.Subcomponent;", 260 "import java.util.Set;", 261 "", 262 "@Subcomponent", 263 "interface Child {", 264 " Set<Object> objectSet();", 265 "}"); 266 JavaFileObject generatedComponent = 267 JavaFileObjects.forSourceLines( 268 "test.DaggerParent", 269 "package test;", 270 "", 271 "import com.google.common.collect.ImmutableSet;", 272 "", 273 GeneratedLines.generatedAnnotations(), 274 "final class DaggerParent implements Parent {", 275 " private static final class ChildImpl implements Child {", 276 " @Override", 277 " public Set<Object> objectSet() {", 278 " return ImmutableSet.<Object>of(", 279 " ParentModule_ParentObjectFactory.parentObject());", 280 " }", 281 " }", 282 "}"); 283 Compilation compilation = 284 compilerWithOptions(compilerMode.javacopts()).compile(parent, parentModule, child); 285 assertThat(compilation).succeeded(); 286 assertThat(compilation) 287 .generatedSourceFile("test.DaggerParent") 288 .containsElementsIn(generatedComponent); 289 } 290 291 @Test productionComponents()292 public void productionComponents() { 293 JavaFileObject emptySetModuleFile = JavaFileObjects.forSourceLines("test.EmptySetModule", 294 "package test;", 295 "", 296 "import dagger.Module;", 297 "import dagger.Provides;", 298 "import dagger.multibindings.ElementsIntoSet;", 299 "import java.util.Collections;", 300 "import java.util.Set;", 301 "", 302 "@Module", 303 "abstract class EmptySetModule {", 304 " @Provides @ElementsIntoSet", 305 " static Set<String> emptySet() { ", 306 " return Collections.emptySet();", 307 " }", 308 "}"); 309 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 310 "package test;", 311 "", 312 "import com.google.common.util.concurrent.ListenableFuture;", 313 "import dagger.producers.ProductionComponent;", 314 "import java.util.Set;", 315 "", 316 "@ProductionComponent(modules = EmptySetModule.class)", 317 "interface TestComponent {", 318 " ListenableFuture<Set<String>> strings();", 319 "}"); 320 JavaFileObject generatedComponent = 321 JavaFileObjects.forSourceLines( 322 "test.DaggerTestComponent", 323 "package test;", 324 "", 325 GeneratedLines.generatedImports( 326 "import com.google.common.collect.ImmutableSet;", 327 "import com.google.common.util.concurrent.Futures;", 328 "import com.google.common.util.concurrent.ListenableFuture;", 329 "import dagger.producers.internal.CancellationListener;", 330 "import java.util.Set;"), 331 "", 332 GeneratedLines.generatedAnnotations(), 333 "final class DaggerTestComponent implements TestComponent, ", 334 " CancellationListener {", 335 " private final DaggerTestComponent testComponent = this;", 336 "", 337 " private DaggerTestComponent() {}", 338 "", 339 " public static Builder builder() {", 340 " return new Builder();", 341 " }", 342 "", 343 " public static TestComponent create() {", 344 " return new Builder().build();", 345 " }", 346 "", 347 " private Set<String> setOfString() {", 348 " return ImmutableSet.<String>copyOf(", 349 " EmptySetModule_EmptySetFactory.emptySet());", 350 " }", 351 "", 352 " @Override", 353 " public ListenableFuture<Set<String>> strings() {", 354 " return Futures.immediateFuture(setOfString());", 355 " }", 356 "", 357 " @Override", 358 " public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {}", 359 "", 360 " static final class Builder {", 361 " private Builder() {}", 362 "", 363 " public TestComponent build() {", 364 " return new DaggerTestComponent();", 365 " }", 366 " }", 367 "}"); 368 369 Compilation compilation = 370 compilerWithOptions(compilerMode.javacopts()) 371 .compile(emptySetModuleFile, componentFile); 372 assertThat(compilation).succeeded(); 373 assertThat(compilation) 374 .generatedSourceFile("test.DaggerTestComponent") 375 .hasSourceEquivalentTo(generatedComponent); 376 } 377 } 378