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 androidx.room.compiler.processing.util.Source; 20 import dagger.testing.compile.CompilerTests; 21 import dagger.testing.golden.GoldenFileRule; 22 import java.util.Collection; 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 ComponentRequirementFieldTest { 31 @Parameters(name = "{0}") parameters()32 public static Collection<Object[]> parameters() { 33 return CompilerMode.TEST_PARAMETERS; 34 } 35 36 @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule(); 37 38 private final CompilerMode compilerMode; 39 ComponentRequirementFieldTest(CompilerMode compilerMode)40 public ComponentRequirementFieldTest(CompilerMode compilerMode) { 41 this.compilerMode = compilerMode; 42 } 43 44 @Test bindsInstance()45 public void bindsInstance() throws Exception { 46 Source component = 47 CompilerTests.javaSource( 48 "test.TestComponent", 49 "package test;", 50 "", 51 "import dagger.BindsInstance;", 52 "import dagger.Component;", 53 "import java.util.List;", 54 "", 55 "@Component", 56 "interface TestComponent {", 57 " int i();", 58 " List<String> list();", 59 "", 60 " @Component.Builder", 61 " interface Builder {", 62 " @BindsInstance Builder i(int i);", 63 " @BindsInstance Builder list(List<String> list);", 64 " TestComponent build();", 65 " }", 66 "}"); 67 CompilerTests.daggerCompiler(component) 68 .withProcessingOptions(compilerMode.processorOptions()) 69 .compile( 70 subject -> { 71 subject.hasErrorCount(0); 72 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 73 }); 74 } 75 76 @Test instanceModuleMethod()77 public void instanceModuleMethod() throws Exception { 78 Source module = 79 CompilerTests.javaSource( 80 "test.ParentModule", 81 "package test;", 82 "", 83 "import dagger.Module;", 84 "import dagger.Provides;", 85 "", 86 "@Module", 87 "class ParentModule {", 88 " @Provides int i() { return 0; }", 89 "}"); 90 Source otherPackageModule = 91 CompilerTests.javaSource( 92 "other.OtherPackageModule", 93 "package other;", 94 "", 95 "import dagger.Module;", 96 "import dagger.Provides;", 97 "", 98 "@Module", 99 "public class OtherPackageModule {", 100 " @Provides long l() { return 0L; }", 101 "}"); 102 Source component = 103 CompilerTests.javaSource( 104 "test.TestComponent", 105 "package test;", 106 "", 107 "import dagger.Component;", 108 "import other.OtherPackageModule;", 109 "", 110 "@Component(modules = {ParentModule.class, OtherPackageModule.class})", 111 "interface TestComponent {", 112 " int i();", 113 " long l();", 114 "}"); 115 CompilerTests.daggerCompiler(module, otherPackageModule, component) 116 .withProcessingOptions(compilerMode.processorOptions()) 117 .compile( 118 subject -> { 119 subject.hasErrorCount(0); 120 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 121 }); 122 } 123 124 @Test componentInstances()125 public void componentInstances() throws Exception { 126 Source dependency = 127 CompilerTests.javaSource( 128 "test.Dep", 129 "package test;", 130 "", 131 "interface Dep {", 132 " String string();", 133 " Object object();", 134 "}"); 135 136 Source component = 137 CompilerTests.javaSource( 138 "test.TestComponent", 139 "package test;", 140 "", 141 "import dagger.Component;", 142 "", 143 "@Component(dependencies = Dep.class)", 144 "interface TestComponent {", 145 " TestComponent self();", 146 " TestSubcomponent subcomponent();", 147 "", 148 " Dep dep();", 149 " String methodOnDep();", 150 " Object otherMethodOnDep();", 151 "}"); 152 Source subcomponent = 153 CompilerTests.javaSource( 154 "test.TestSubcomponent", 155 "package test;", 156 "", 157 "import dagger.Subcomponent;", 158 "", 159 "@Subcomponent", 160 "interface TestSubcomponent {", 161 " TestComponent parent();", 162 " Dep depFromSubcomponent();", 163 "}"); 164 165 CompilerTests.daggerCompiler(dependency, component, subcomponent) 166 .withProcessingOptions(compilerMode.processorOptions()) 167 .compile( 168 subject -> { 169 subject.hasErrorCount(0); 170 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 171 }); 172 } 173 174 @Test componentRequirementNeededInFactoryCreationOfSubcomponent()175 public void componentRequirementNeededInFactoryCreationOfSubcomponent() throws Exception { 176 Source parentModule = 177 CompilerTests.javaSource( 178 "test.ParentModule", 179 "package test;", 180 "", 181 "import dagger.Module;", 182 "import dagger.multibindings.IntoSet;", 183 "import dagger.Provides;", 184 "import java.util.Set;", 185 "", 186 "@Module", 187 "class ParentModule {", 188 " @Provides", 189 // intentionally non-static. this needs to require the module when the subcompnent 190 // adds to the Set binding 191 " Object reliesOnMultibinding(Set<Object> set) { return set; }", 192 "", 193 " @Provides @IntoSet static Object contribution() { return new Object(); }", 194 "}"); 195 196 Source childModule = 197 CompilerTests.javaSource( 198 "test.ChildModule", 199 "package test;", 200 "", 201 "import dagger.Module;", 202 "import dagger.multibindings.IntoSet;", 203 "import dagger.Provides;", 204 "", 205 "@Module", 206 "class ChildModule {", 207 " @Provides @IntoSet static Object contribution() { return new Object(); }", 208 "}"); 209 210 Source component = 211 CompilerTests.javaSource( 212 "test.TestComponent", 213 "package test;", 214 "", 215 "import dagger.Component;", 216 "import javax.inject.Provider;", 217 "", 218 "@Component(modules = ParentModule.class)", 219 "interface TestComponent {", 220 " Provider<Object> dependsOnMultibinding();", 221 " TestSubcomponent subcomponent();", 222 "}"); 223 224 Source subcomponent = 225 CompilerTests.javaSource( 226 "test.TestSubcomponent", 227 "package test;", 228 "", 229 "import dagger.Subcomponent;", 230 "import javax.inject.Provider;", 231 "", 232 "@Subcomponent(modules = ChildModule.class)", 233 "interface TestSubcomponent {", 234 " Provider<Object> dependsOnMultibinding();", 235 "}"); 236 237 CompilerTests.daggerCompiler(parentModule, childModule, component, subcomponent) 238 .withProcessingOptions(compilerMode.processorOptions()) 239 .compile( 240 subject -> { 241 subject.hasErrorCount(0); 242 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 243 }); 244 } 245 } 246