1*f585d8a3SJacky Wang /* 2*f585d8a3SJacky Wang * Copyright (C) 2020 The Dagger Authors. 3*f585d8a3SJacky Wang * 4*f585d8a3SJacky Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5*f585d8a3SJacky Wang * you may not use this file except in compliance with the License. 6*f585d8a3SJacky Wang * You may obtain a copy of the License at 7*f585d8a3SJacky Wang * 8*f585d8a3SJacky Wang * http://www.apache.org/licenses/LICENSE-2.0 9*f585d8a3SJacky Wang * 10*f585d8a3SJacky Wang * Unless required by applicable law or agreed to in writing, software 11*f585d8a3SJacky Wang * distributed under the License is distributed on an "AS IS" BASIS, 12*f585d8a3SJacky Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*f585d8a3SJacky Wang * See the License for the specific language governing permissions and 14*f585d8a3SJacky Wang * limitations under the License. 15*f585d8a3SJacky Wang */ 16*f585d8a3SJacky Wang 17*f585d8a3SJacky Wang package dagger.internal.codegen; 18*f585d8a3SJacky Wang 19*f585d8a3SJacky Wang import static java.util.stream.Collectors.joining; 20*f585d8a3SJacky Wang 21*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.Source; 22*f585d8a3SJacky Wang import com.google.common.collect.ImmutableList; 23*f585d8a3SJacky Wang import com.google.common.collect.ImmutableMap; 24*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests; 25*f585d8a3SJacky Wang import dagger.testing.golden.GoldenFileRule; 26*f585d8a3SJacky Wang import java.util.Arrays; 27*f585d8a3SJacky Wang import org.junit.Rule; 28*f585d8a3SJacky Wang import org.junit.Test; 29*f585d8a3SJacky Wang import org.junit.runner.RunWith; 30*f585d8a3SJacky Wang import org.junit.runners.Parameterized; 31*f585d8a3SJacky Wang import org.junit.runners.Parameterized.Parameters; 32*f585d8a3SJacky Wang 33*f585d8a3SJacky Wang @RunWith(Parameterized.class) 34*f585d8a3SJacky Wang public class ComponentShardTest { 35*f585d8a3SJacky Wang private static final int BINDINGS_PER_SHARD = 2; 36*f585d8a3SJacky Wang 37*f585d8a3SJacky Wang @Parameters(name = "{0}") parameters()38*f585d8a3SJacky Wang public static ImmutableList<Object[]> parameters() { 39*f585d8a3SJacky Wang return CompilerMode.TEST_PARAMETERS; 40*f585d8a3SJacky Wang } 41*f585d8a3SJacky Wang 42*f585d8a3SJacky Wang @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule(); 43*f585d8a3SJacky Wang 44*f585d8a3SJacky Wang private final CompilerMode compilerMode; 45*f585d8a3SJacky Wang ComponentShardTest(CompilerMode compilerMode)46*f585d8a3SJacky Wang public ComponentShardTest(CompilerMode compilerMode) { 47*f585d8a3SJacky Wang this.compilerMode = compilerMode; 48*f585d8a3SJacky Wang } 49*f585d8a3SJacky Wang 50*f585d8a3SJacky Wang @Test testNewShardCreated()51*f585d8a3SJacky Wang public void testNewShardCreated() throws Exception { 52*f585d8a3SJacky Wang // Add all bindings. 53*f585d8a3SJacky Wang // 54*f585d8a3SJacky Wang // 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 55*f585d8a3SJacky Wang // ^--------/ 56*f585d8a3SJacky Wang // 57*f585d8a3SJacky Wang ImmutableList.Builder<Source> sources = ImmutableList.builder(); 58*f585d8a3SJacky Wang sources 59*f585d8a3SJacky Wang // Shard 2: Bindings (1) 60*f585d8a3SJacky Wang .add(createBinding("Binding1", "Binding2 binding2")) 61*f585d8a3SJacky Wang // Shard 1: Bindings (2, 3, 4, 5). Contains more than 2 bindings due to cycle. 62*f585d8a3SJacky Wang .add(createBinding("Binding2", "Binding3 binding3")) 63*f585d8a3SJacky Wang .add(createBinding("Binding3", "Binding4 binding4")) 64*f585d8a3SJacky Wang .add(createBinding("Binding4", "Binding5 binding5, Provider<Binding2> binding2Provider")) 65*f585d8a3SJacky Wang .add(createBinding("Binding5", "Binding6 binding6")) 66*f585d8a3SJacky Wang // Component shard: Bindings (6, 7) 67*f585d8a3SJacky Wang .add(createBinding("Binding6", "Binding7 binding7")) 68*f585d8a3SJacky Wang .add(createBinding("Binding7")); 69*f585d8a3SJacky Wang 70*f585d8a3SJacky Wang // Add the component with entry points for each binding and its provider. 71*f585d8a3SJacky Wang sources.add( 72*f585d8a3SJacky Wang CompilerTests.javaSource( 73*f585d8a3SJacky Wang "dagger.internal.codegen.TestComponent", 74*f585d8a3SJacky Wang "package dagger.internal.codegen;", 75*f585d8a3SJacky Wang "", 76*f585d8a3SJacky Wang "import dagger.Component;", 77*f585d8a3SJacky Wang "import javax.inject.Provider;", 78*f585d8a3SJacky Wang "import javax.inject.Singleton;", 79*f585d8a3SJacky Wang "", 80*f585d8a3SJacky Wang "@Singleton", 81*f585d8a3SJacky Wang "@Component", 82*f585d8a3SJacky Wang "interface TestComponent {", 83*f585d8a3SJacky Wang " Binding1 binding1();", 84*f585d8a3SJacky Wang " Binding2 binding2();", 85*f585d8a3SJacky Wang " Binding3 binding3();", 86*f585d8a3SJacky Wang " Binding4 binding4();", 87*f585d8a3SJacky Wang " Binding5 binding5();", 88*f585d8a3SJacky Wang " Binding6 binding6();", 89*f585d8a3SJacky Wang " Binding7 binding7();", 90*f585d8a3SJacky Wang " Provider<Binding1> providerBinding1();", 91*f585d8a3SJacky Wang " Provider<Binding2> providerBinding2();", 92*f585d8a3SJacky Wang " Provider<Binding3> providerBinding3();", 93*f585d8a3SJacky Wang " Provider<Binding4> providerBinding4();", 94*f585d8a3SJacky Wang " Provider<Binding5> providerBinding5();", 95*f585d8a3SJacky Wang " Provider<Binding6> providerBinding6();", 96*f585d8a3SJacky Wang " Provider<Binding7> providerBinding7();", 97*f585d8a3SJacky Wang "}")); 98*f585d8a3SJacky Wang 99*f585d8a3SJacky Wang CompilerTests.daggerCompiler(sources.build()) 100*f585d8a3SJacky Wang .withProcessingOptions(compilerOptions()) 101*f585d8a3SJacky Wang .compile( 102*f585d8a3SJacky Wang subject -> { 103*f585d8a3SJacky Wang subject.hasErrorCount(0); 104*f585d8a3SJacky Wang subject.generatedSource( 105*f585d8a3SJacky Wang goldenFileRule.goldenSource("dagger/internal/codegen/DaggerTestComponent")); 106*f585d8a3SJacky Wang }); 107*f585d8a3SJacky Wang } 108*f585d8a3SJacky Wang 109*f585d8a3SJacky Wang @Test testNewShardCreatedWithDependencies()110*f585d8a3SJacky Wang public void testNewShardCreatedWithDependencies() throws Exception { 111*f585d8a3SJacky Wang ImmutableList.Builder<Source> sources = ImmutableList.builder(); 112*f585d8a3SJacky Wang sources.add( 113*f585d8a3SJacky Wang createBinding("Binding1"), 114*f585d8a3SJacky Wang createBinding("Binding2"), 115*f585d8a3SJacky Wang CompilerTests.javaSource( 116*f585d8a3SJacky Wang "dagger.internal.codegen.Binding3", 117*f585d8a3SJacky Wang "package dagger.internal.codegen;", 118*f585d8a3SJacky Wang "", 119*f585d8a3SJacky Wang "class Binding3 {}"), 120*f585d8a3SJacky Wang CompilerTests.javaSource( 121*f585d8a3SJacky Wang "dagger.internal.codegen.Dependency", 122*f585d8a3SJacky Wang "package dagger.internal.codegen;", 123*f585d8a3SJacky Wang "", 124*f585d8a3SJacky Wang "interface Dependency {", 125*f585d8a3SJacky Wang " Binding3 binding3();", 126*f585d8a3SJacky Wang "}"), 127*f585d8a3SJacky Wang CompilerTests.javaSource( 128*f585d8a3SJacky Wang "dagger.internal.codegen.TestComponent", 129*f585d8a3SJacky Wang "package dagger.internal.codegen;", 130*f585d8a3SJacky Wang "", 131*f585d8a3SJacky Wang "import dagger.Component;", 132*f585d8a3SJacky Wang "import javax.inject.Provider;", 133*f585d8a3SJacky Wang "import javax.inject.Singleton;", 134*f585d8a3SJacky Wang "", 135*f585d8a3SJacky Wang "@Singleton", 136*f585d8a3SJacky Wang "@Component(dependencies = Dependency.class)", 137*f585d8a3SJacky Wang "interface TestComponent {", 138*f585d8a3SJacky Wang " Binding1 binding1();", 139*f585d8a3SJacky Wang " Binding2 binding2();", 140*f585d8a3SJacky Wang " Binding3 binding3();", 141*f585d8a3SJacky Wang " Provider<Binding1> providerBinding1();", 142*f585d8a3SJacky Wang " Provider<Binding2> providerBinding2();", 143*f585d8a3SJacky Wang " Provider<Binding3> providerBinding3();", 144*f585d8a3SJacky Wang "}")); 145*f585d8a3SJacky Wang 146*f585d8a3SJacky Wang CompilerTests.daggerCompiler(sources.build()) 147*f585d8a3SJacky Wang .withProcessingOptions(compilerOptions()) 148*f585d8a3SJacky Wang .compile( 149*f585d8a3SJacky Wang subject -> { 150*f585d8a3SJacky Wang subject.hasErrorCount(0); 151*f585d8a3SJacky Wang subject.generatedSource( 152*f585d8a3SJacky Wang goldenFileRule.goldenSource("dagger/internal/codegen/DaggerTestComponent")); 153*f585d8a3SJacky Wang }); 154*f585d8a3SJacky Wang } 155*f585d8a3SJacky Wang 156*f585d8a3SJacky Wang @Test testNewShardSubcomponentCreated()157*f585d8a3SJacky Wang public void testNewShardSubcomponentCreated() throws Exception { 158*f585d8a3SJacky Wang ImmutableList.Builder<Source> sources = ImmutableList.builder(); 159*f585d8a3SJacky Wang sources.add( 160*f585d8a3SJacky Wang CompilerTests.javaSource( 161*f585d8a3SJacky Wang "dagger.internal.codegen.SubcomponentScope", 162*f585d8a3SJacky Wang "package dagger.internal.codegen;", 163*f585d8a3SJacky Wang "", 164*f585d8a3SJacky Wang "import javax.inject.Scope;", 165*f585d8a3SJacky Wang "", 166*f585d8a3SJacky Wang "@Scope", 167*f585d8a3SJacky Wang "public @interface SubcomponentScope {}"), 168*f585d8a3SJacky Wang CompilerTests.javaSource( 169*f585d8a3SJacky Wang "dagger.internal.codegen.Binding1", 170*f585d8a3SJacky Wang "package dagger.internal.codegen;", 171*f585d8a3SJacky Wang "", 172*f585d8a3SJacky Wang "@SubcomponentScope", 173*f585d8a3SJacky Wang "final class Binding1 {", 174*f585d8a3SJacky Wang " @javax.inject.Inject Binding1() {}", 175*f585d8a3SJacky Wang "}"), 176*f585d8a3SJacky Wang CompilerTests.javaSource( 177*f585d8a3SJacky Wang "dagger.internal.codegen.Binding2", 178*f585d8a3SJacky Wang "package dagger.internal.codegen;", 179*f585d8a3SJacky Wang "", 180*f585d8a3SJacky Wang "@SubcomponentScope", 181*f585d8a3SJacky Wang "final class Binding2 {", 182*f585d8a3SJacky Wang " @javax.inject.Inject Binding2() {}", 183*f585d8a3SJacky Wang "}"), 184*f585d8a3SJacky Wang CompilerTests.javaSource( 185*f585d8a3SJacky Wang "dagger.internal.codegen.Binding3", 186*f585d8a3SJacky Wang "package dagger.internal.codegen;", 187*f585d8a3SJacky Wang "", 188*f585d8a3SJacky Wang "@SubcomponentScope", 189*f585d8a3SJacky Wang "final class Binding3 {", 190*f585d8a3SJacky Wang " @javax.inject.Inject Binding3() {}", 191*f585d8a3SJacky Wang "}"), 192*f585d8a3SJacky Wang CompilerTests.javaSource( 193*f585d8a3SJacky Wang "dagger.internal.codegen.TestComponent", 194*f585d8a3SJacky Wang "package dagger.internal.codegen;", 195*f585d8a3SJacky Wang "", 196*f585d8a3SJacky Wang "import dagger.Component;", 197*f585d8a3SJacky Wang "", 198*f585d8a3SJacky Wang "@Component", 199*f585d8a3SJacky Wang "interface TestComponent {", 200*f585d8a3SJacky Wang " TestSubcomponent subcomponent();", 201*f585d8a3SJacky Wang "}"), 202*f585d8a3SJacky Wang CompilerTests.javaSource( 203*f585d8a3SJacky Wang "dagger.internal.codegen.TestSubcomponent", 204*f585d8a3SJacky Wang "package dagger.internal.codegen;", 205*f585d8a3SJacky Wang "", 206*f585d8a3SJacky Wang "import dagger.Subcomponent;", 207*f585d8a3SJacky Wang "import javax.inject.Provider;", 208*f585d8a3SJacky Wang "", 209*f585d8a3SJacky Wang "@SubcomponentScope", 210*f585d8a3SJacky Wang "@Subcomponent", 211*f585d8a3SJacky Wang "interface TestSubcomponent {", 212*f585d8a3SJacky Wang " Binding1 binding1();", 213*f585d8a3SJacky Wang " Binding2 binding2();", 214*f585d8a3SJacky Wang " Binding3 binding3();", 215*f585d8a3SJacky Wang " Provider<Binding1> providerBinding1();", 216*f585d8a3SJacky Wang " Provider<Binding2> providerBinding2();", 217*f585d8a3SJacky Wang " Provider<Binding3> providerBinding3();", 218*f585d8a3SJacky Wang "}")); 219*f585d8a3SJacky Wang 220*f585d8a3SJacky Wang CompilerTests.daggerCompiler(sources.build()) 221*f585d8a3SJacky Wang .withProcessingOptions(compilerOptions()) 222*f585d8a3SJacky Wang .compile( 223*f585d8a3SJacky Wang subject -> { 224*f585d8a3SJacky Wang subject.hasErrorCount(0); 225*f585d8a3SJacky Wang subject.generatedSource( 226*f585d8a3SJacky Wang goldenFileRule.goldenSource("dagger/internal/codegen/DaggerTestComponent")); 227*f585d8a3SJacky Wang }); 228*f585d8a3SJacky Wang } 229*f585d8a3SJacky Wang createBinding(String bindingName, String... deps)230*f585d8a3SJacky Wang private static Source createBinding(String bindingName, String... deps) { 231*f585d8a3SJacky Wang return CompilerTests.javaSource( 232*f585d8a3SJacky Wang "dagger.internal.codegen." + bindingName, 233*f585d8a3SJacky Wang "package dagger.internal.codegen;", 234*f585d8a3SJacky Wang "", 235*f585d8a3SJacky Wang "import javax.inject.Inject;", 236*f585d8a3SJacky Wang "import javax.inject.Provider;", 237*f585d8a3SJacky Wang "import javax.inject.Singleton;", 238*f585d8a3SJacky Wang "", 239*f585d8a3SJacky Wang "@Singleton", 240*f585d8a3SJacky Wang "final class " + bindingName + " {", 241*f585d8a3SJacky Wang " @Inject", 242*f585d8a3SJacky Wang " " + bindingName + "(" + Arrays.stream(deps).collect(joining(", ")) + ") {}", 243*f585d8a3SJacky Wang "}"); 244*f585d8a3SJacky Wang } 245*f585d8a3SJacky Wang compilerOptions()246*f585d8a3SJacky Wang private ImmutableMap<String, String> compilerOptions() { 247*f585d8a3SJacky Wang return ImmutableMap.<String, String>builder() 248*f585d8a3SJacky Wang .putAll(compilerMode.processorOptions()) 249*f585d8a3SJacky Wang .put("dagger.generatedClassExtendsComponent", "DISABLED") 250*f585d8a3SJacky Wang .put("dagger.keysPerComponentShard", Integer.toString(BINDINGS_PER_SHARD)) 251*f585d8a3SJacky Wang .buildOrThrow(); 252*f585d8a3SJacky Wang } 253*f585d8a3SJacky Wang } 254