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.internal.codegen; 18 19 import static com.google.testing.compile.CompilationSubject.assertThat; 20 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE; 21 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE; 22 import static dagger.internal.codegen.Compilers.compilerWithOptions; 23 import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS; 24 25 import com.google.common.collect.ImmutableCollection; 26 import com.google.testing.compile.Compilation; 27 import com.google.testing.compile.JavaFileObjects; 28 import javax.tools.JavaFileObject; 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 import org.junit.runners.Parameterized; 32 import org.junit.runners.Parameterized.Parameters; 33 34 @RunWith(Parameterized.class) 35 public class AssistedFactoryTest { 36 @Parameters(name = "{0}") parameters()37 public static ImmutableCollection<Object[]> parameters() { 38 return CompilerMode.TEST_PARAMETERS; 39 } 40 41 private final CompilerMode compilerMode; 42 AssistedFactoryTest(CompilerMode compilerMode)43 public AssistedFactoryTest(CompilerMode compilerMode) { 44 this.compilerMode = compilerMode; 45 } 46 47 @Test testAssistedFactory()48 public void testAssistedFactory() { 49 JavaFileObject foo = 50 JavaFileObjects.forSourceLines( 51 "test.Foo", 52 "package test;", 53 "", 54 "import dagger.assisted.Assisted;", 55 "import dagger.assisted.AssistedInject;", 56 "", 57 "class Foo {", 58 " @AssistedInject", 59 " Foo(@Assisted String str, Bar bar) {}", 60 "}"); 61 JavaFileObject fooFactory = 62 JavaFileObjects.forSourceLines( 63 "test.FooFactory", 64 "package test;", 65 "", 66 "import dagger.assisted.AssistedFactory;", 67 "", 68 "@AssistedFactory", 69 "interface FooFactory {", 70 " Foo create(String factoryStr);", 71 "}"); 72 JavaFileObject bar = 73 JavaFileObjects.forSourceLines( 74 "test.Bar", 75 "package test;", 76 "", 77 "import javax.inject.Inject;", 78 "", 79 "class Bar {", 80 " @Inject Bar() {}", 81 "}"); 82 JavaFileObject component = 83 JavaFileObjects.forSourceLines( 84 "test.TestComponent", 85 "package test;", 86 "", 87 "import dagger.Component;", 88 "", 89 "@Component", 90 "interface TestComponent {", 91 " FooFactory fooFactory();", 92 "}"); 93 Compilation compilation = 94 compilerWithOptions(compilerMode.javacopts()).compile(foo, bar, fooFactory, component); 95 assertThat(compilation).succeeded(); 96 JavaFileObject generatedComponent = 97 compilerMode 98 .javaFileBuilder("test.DaggerTestComponent") 99 .addLines("package test;", "", GENERATED_CODE_ANNOTATIONS) 100 .addLinesIn( 101 FAST_INIT_MODE, 102 "final class DaggerTestComponent implements TestComponent {", 103 "", 104 " private Foo foo(String str) {", 105 " return new Foo(str, new Bar());", 106 " }", 107 "", 108 " @Override", 109 " public FooFactory fooFactory() {", 110 " return new FooFactory() {", 111 " @Override", 112 " public Foo create(String str) {", 113 " return DaggerTestComponent.this.foo(str);", 114 " }", 115 " };", 116 " }", 117 "}") 118 .addLinesIn( 119 DEFAULT_MODE, 120 "final class DaggerTestComponent implements TestComponent {", 121 "", 122 " private Foo_Factory fooProvider;", 123 "", 124 " private Provider<FooFactory> fooFactoryProvider;", 125 "", 126 " @SuppressWarnings(\"unchecked\")", 127 " private void initialize() {", 128 " this.fooProvider = Foo_Factory.create(Bar_Factory.create());", 129 " this.fooFactoryProvider = FooFactory_Impl.create(fooProvider);", 130 " }", 131 "", 132 " @Override", 133 " public FooFactory fooFactory() {", 134 " return fooFactoryProvider.get();", 135 " }", 136 "}") 137 .build(); 138 assertThat(compilation) 139 .generatedSourceFile("test.DaggerTestComponent") 140 .containsElementsIn(generatedComponent); 141 } 142 143 @Test testAssistedFactoryCycle()144 public void testAssistedFactoryCycle() { 145 JavaFileObject foo = 146 JavaFileObjects.forSourceLines( 147 "test.Foo", 148 "package test;", 149 "", 150 "import dagger.assisted.Assisted;", 151 "import dagger.assisted.AssistedInject;", 152 "", 153 "class Foo {", 154 " @AssistedInject", 155 " Foo(@Assisted String str, Bar bar) {}", 156 "}"); 157 JavaFileObject fooFactory = 158 JavaFileObjects.forSourceLines( 159 "test.FooFactory", 160 "package test;", 161 "", 162 "import dagger.assisted.AssistedFactory;", 163 "", 164 "@AssistedFactory", 165 "interface FooFactory {", 166 " Foo create(String factoryStr);", 167 "}"); 168 JavaFileObject bar = 169 JavaFileObjects.forSourceLines( 170 "test.Bar", 171 "package test;", 172 "", 173 "import javax.inject.Inject;", 174 "", 175 "class Bar {", 176 " @Inject Bar(FooFactory fooFactory) {}", 177 "}"); 178 JavaFileObject component = 179 JavaFileObjects.forSourceLines( 180 "test.TestComponent", 181 "package test;", 182 "", 183 "import dagger.Component;", 184 "", 185 "@Component", 186 "interface TestComponent {", 187 " FooFactory fooFactory();", 188 "}"); 189 Compilation compilation = 190 compilerWithOptions(compilerMode.javacopts()).compile(foo, bar, fooFactory, component); 191 assertThat(compilation).succeeded(); 192 JavaFileObject generatedComponent = 193 compilerMode 194 .javaFileBuilder("test.DaggerTestComponent") 195 .addLines("package test;", "", GENERATED_CODE_ANNOTATIONS) 196 .addLinesIn( 197 FAST_INIT_MODE, 198 "final class DaggerTestComponent implements TestComponent {", 199 "", 200 " private Bar bar() {", 201 " return new Bar(fooFactory());", 202 " }", 203 "", 204 " private Foo foo(String str) {", 205 " return new Foo(str, bar());", 206 " }", 207 "", 208 " @Override", 209 " public FooFactory fooFactory() {", 210 " return new FooFactory() {", 211 " @Override", 212 " public Foo create(String str) {", 213 " return DaggerTestComponent.this.foo(str);", 214 " }", 215 " };", 216 " }", 217 "}") 218 .addLinesIn( 219 DEFAULT_MODE, 220 "final class DaggerTestComponent implements TestComponent {", 221 "", 222 " private Provider<FooFactory> fooFactoryProvider;", 223 "", 224 " private Provider<Bar> barProvider;", 225 "", 226 " private Foo_Factory fooProvider;", 227 "", 228 " @SuppressWarnings(\"unchecked\")", 229 " private void initialize() {", 230 " this.fooFactoryProvider = new DelegateFactory<>();", 231 " this.barProvider = Bar_Factory.create(fooFactoryProvider);", 232 " this.fooProvider = Foo_Factory.create(barProvider);", 233 " DelegateFactory.setDelegate(", 234 " fooFactoryProvider, FooFactory_Impl.create(fooProvider));", 235 " }", 236 "", 237 " @Override", 238 " public FooFactory fooFactory() {", 239 " return fooFactoryProvider.get();", 240 " }", 241 "}") 242 .build(); 243 assertThat(compilation) 244 .generatedSourceFile("test.DaggerTestComponent") 245 .containsElementsIn(generatedComponent); 246 } 247 } 248