1*f585d8a3SJacky Wang /*
2*f585d8a3SJacky Wang  * Copyright (C) 2017 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 com.google.testing.compile.CompilationSubject.assertThat;
20*f585d8a3SJacky Wang import static dagger.internal.codegen.Compilers.CLASS_PATH_WITHOUT_GUAVA_OPTION;
21*f585d8a3SJacky Wang import static dagger.internal.codegen.Compilers.compilerWithOptions;
22*f585d8a3SJacky Wang 
23*f585d8a3SJacky Wang import com.google.testing.compile.Compilation;
24*f585d8a3SJacky Wang import com.google.testing.compile.Compiler;
25*f585d8a3SJacky Wang import com.google.testing.compile.JavaFileObjects;
26*f585d8a3SJacky Wang import dagger.testing.golden.GoldenFileRule;
27*f585d8a3SJacky Wang import java.util.Collection;
28*f585d8a3SJacky Wang import javax.tools.JavaFileObject;
29*f585d8a3SJacky Wang import org.junit.Rule;
30*f585d8a3SJacky Wang import org.junit.Test;
31*f585d8a3SJacky Wang import org.junit.runner.RunWith;
32*f585d8a3SJacky Wang import org.junit.runners.Parameterized;
33*f585d8a3SJacky Wang import org.junit.runners.Parameterized.Parameters;
34*f585d8a3SJacky Wang 
35*f585d8a3SJacky Wang @RunWith(Parameterized.class)
36*f585d8a3SJacky Wang public class SetBindingRequestFulfillmentTest {
37*f585d8a3SJacky Wang   @Parameters(name = "{0}")
parameters()38*f585d8a3SJacky Wang   public static Collection<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 
SetBindingRequestFulfillmentTest(CompilerMode compilerMode)46*f585d8a3SJacky Wang   public SetBindingRequestFulfillmentTest(CompilerMode compilerMode) {
47*f585d8a3SJacky Wang     this.compilerMode = compilerMode;
48*f585d8a3SJacky Wang   }
49*f585d8a3SJacky Wang 
50*f585d8a3SJacky Wang   @Test
setBindings()51*f585d8a3SJacky Wang   public void setBindings() throws Exception {
52*f585d8a3SJacky Wang     JavaFileObject emptySetModuleFile = JavaFileObjects.forSourceLines("test.EmptySetModule",
53*f585d8a3SJacky Wang         "package test;",
54*f585d8a3SJacky Wang         "",
55*f585d8a3SJacky Wang         "import dagger.Module;",
56*f585d8a3SJacky Wang         "import dagger.Provides;",
57*f585d8a3SJacky Wang         "import dagger.multibindings.ElementsIntoSet;",
58*f585d8a3SJacky Wang         "import dagger.multibindings.Multibinds;",
59*f585d8a3SJacky Wang         "import java.util.Collections;",
60*f585d8a3SJacky Wang         "import java.util.Set;",
61*f585d8a3SJacky Wang         "",
62*f585d8a3SJacky Wang         "@Module",
63*f585d8a3SJacky Wang         "abstract class EmptySetModule {",
64*f585d8a3SJacky Wang         "  @Multibinds abstract Set<Object> objects();",
65*f585d8a3SJacky Wang         "",
66*f585d8a3SJacky Wang         "  @Provides @ElementsIntoSet",
67*f585d8a3SJacky Wang         "  static Set<String> emptySet() { ",
68*f585d8a3SJacky Wang         "    return Collections.emptySet();",
69*f585d8a3SJacky Wang         "  }",
70*f585d8a3SJacky Wang         "}");
71*f585d8a3SJacky Wang     JavaFileObject setModuleFile = JavaFileObjects.forSourceLines("test.SetModule",
72*f585d8a3SJacky Wang         "package test;",
73*f585d8a3SJacky Wang         "",
74*f585d8a3SJacky Wang         "import dagger.Module;",
75*f585d8a3SJacky Wang         "import dagger.Provides;",
76*f585d8a3SJacky Wang         "import dagger.multibindings.IntoSet;",
77*f585d8a3SJacky Wang         "",
78*f585d8a3SJacky Wang         "@Module",
79*f585d8a3SJacky Wang         "final class SetModule {",
80*f585d8a3SJacky Wang         "  @Provides @IntoSet static String string() { return \"\"; }",
81*f585d8a3SJacky Wang         "}");
82*f585d8a3SJacky Wang     JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent",
83*f585d8a3SJacky Wang         "package test;",
84*f585d8a3SJacky Wang         "",
85*f585d8a3SJacky Wang         "import dagger.Component;",
86*f585d8a3SJacky Wang         "import java.util.Set;",
87*f585d8a3SJacky Wang         "import javax.inject.Provider;",
88*f585d8a3SJacky Wang         "",
89*f585d8a3SJacky Wang         "@Component(modules = {EmptySetModule.class, SetModule.class})",
90*f585d8a3SJacky Wang         "interface TestComponent {",
91*f585d8a3SJacky Wang         "  Set<String> strings();",
92*f585d8a3SJacky Wang         "  Set<Object> objects();",
93*f585d8a3SJacky Wang         "}");
94*f585d8a3SJacky Wang 
95*f585d8a3SJacky Wang     Compilation compilation =
96*f585d8a3SJacky Wang         daggerCompilerWithoutGuava().compile(emptySetModuleFile, setModuleFile, componentFile);
97*f585d8a3SJacky Wang     assertThat(compilation).succeeded();
98*f585d8a3SJacky Wang     assertThat(compilation)
99*f585d8a3SJacky Wang         .generatedSourceFile("test.DaggerTestComponent")
100*f585d8a3SJacky Wang         .hasSourceEquivalentTo(goldenFileRule.goldenFile("test.DaggerTestComponent"));
101*f585d8a3SJacky Wang   }
102*f585d8a3SJacky Wang 
103*f585d8a3SJacky Wang   @Test
inaccessible()104*f585d8a3SJacky Wang   public void inaccessible() throws Exception {
105*f585d8a3SJacky Wang     JavaFileObject inaccessible =
106*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
107*f585d8a3SJacky Wang             "other.Inaccessible",
108*f585d8a3SJacky Wang             "package other;",
109*f585d8a3SJacky Wang             "",
110*f585d8a3SJacky Wang             "class Inaccessible {}");
111*f585d8a3SJacky Wang     JavaFileObject inaccessible2 =
112*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
113*f585d8a3SJacky Wang             "other.Inaccessible2",
114*f585d8a3SJacky Wang             "package other;",
115*f585d8a3SJacky Wang             "",
116*f585d8a3SJacky Wang             "class Inaccessible2 {}");
117*f585d8a3SJacky Wang     JavaFileObject usesInaccessible =
118*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
119*f585d8a3SJacky Wang             "other.UsesInaccessible",
120*f585d8a3SJacky Wang             "package other;",
121*f585d8a3SJacky Wang             "",
122*f585d8a3SJacky Wang             "import java.util.Set;",
123*f585d8a3SJacky Wang             "import javax.inject.Inject;",
124*f585d8a3SJacky Wang             "",
125*f585d8a3SJacky Wang             "public class UsesInaccessible {",
126*f585d8a3SJacky Wang             "  @Inject UsesInaccessible(Set<Inaccessible> set1, Set<Inaccessible2> set2) {}",
127*f585d8a3SJacky Wang             "}");
128*f585d8a3SJacky Wang 
129*f585d8a3SJacky Wang     JavaFileObject module =
130*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
131*f585d8a3SJacky Wang             "other.TestModule",
132*f585d8a3SJacky Wang             "package other;",
133*f585d8a3SJacky Wang             "",
134*f585d8a3SJacky Wang             "import dagger.Module;",
135*f585d8a3SJacky Wang             "import dagger.Provides;",
136*f585d8a3SJacky Wang             "import dagger.multibindings.ElementsIntoSet;",
137*f585d8a3SJacky Wang             "import dagger.multibindings.Multibinds;",
138*f585d8a3SJacky Wang             "import java.util.Collections;",
139*f585d8a3SJacky Wang             "import java.util.Set;",
140*f585d8a3SJacky Wang             "",
141*f585d8a3SJacky Wang             "@Module",
142*f585d8a3SJacky Wang             "public abstract class TestModule {",
143*f585d8a3SJacky Wang             "  @Multibinds abstract Set<Inaccessible> objects();",
144*f585d8a3SJacky Wang             "",
145*f585d8a3SJacky Wang             "  @Provides @ElementsIntoSet",
146*f585d8a3SJacky Wang             "  static Set<Inaccessible2> emptySet() { ",
147*f585d8a3SJacky Wang             "    return Collections.emptySet();",
148*f585d8a3SJacky Wang             "  }",
149*f585d8a3SJacky Wang             "}");
150*f585d8a3SJacky Wang     JavaFileObject componentFile =
151*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
152*f585d8a3SJacky Wang             "test.TestComponent",
153*f585d8a3SJacky Wang             "package test;",
154*f585d8a3SJacky Wang             "",
155*f585d8a3SJacky Wang             "import dagger.Component;",
156*f585d8a3SJacky Wang             "import java.util.Set;",
157*f585d8a3SJacky Wang             "import javax.inject.Provider;",
158*f585d8a3SJacky Wang             "import other.TestModule;",
159*f585d8a3SJacky Wang             "import other.UsesInaccessible;",
160*f585d8a3SJacky Wang             "",
161*f585d8a3SJacky Wang             "@Component(modules = TestModule.class)",
162*f585d8a3SJacky Wang             "interface TestComponent {",
163*f585d8a3SJacky Wang             "  UsesInaccessible usesInaccessible();",
164*f585d8a3SJacky Wang             "}");
165*f585d8a3SJacky Wang 
166*f585d8a3SJacky Wang     Compilation compilation =
167*f585d8a3SJacky Wang         daggerCompilerWithoutGuava()
168*f585d8a3SJacky Wang             .compile(module, inaccessible, inaccessible2, usesInaccessible, componentFile);
169*f585d8a3SJacky Wang     assertThat(compilation).succeeded();
170*f585d8a3SJacky Wang     assertThat(compilation)
171*f585d8a3SJacky Wang         .generatedSourceFile("test.DaggerTestComponent")
172*f585d8a3SJacky Wang         .hasSourceEquivalentTo(goldenFileRule.goldenFile("test.DaggerTestComponent"));
173*f585d8a3SJacky Wang   }
174*f585d8a3SJacky Wang 
175*f585d8a3SJacky Wang   @Test
subcomponentOmitsInheritedBindings()176*f585d8a3SJacky Wang   public void subcomponentOmitsInheritedBindings() throws Exception {
177*f585d8a3SJacky Wang     JavaFileObject parent =
178*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
179*f585d8a3SJacky Wang             "test.Parent",
180*f585d8a3SJacky Wang             "package test;",
181*f585d8a3SJacky Wang             "",
182*f585d8a3SJacky Wang             "import dagger.Component;",
183*f585d8a3SJacky Wang             "",
184*f585d8a3SJacky Wang             "@Component(modules = ParentModule.class)",
185*f585d8a3SJacky Wang             "interface Parent {",
186*f585d8a3SJacky Wang             "  Child child();",
187*f585d8a3SJacky Wang             "}");
188*f585d8a3SJacky Wang     JavaFileObject parentModule =
189*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
190*f585d8a3SJacky Wang             "test.ParentModule",
191*f585d8a3SJacky Wang             "package test;",
192*f585d8a3SJacky Wang             "",
193*f585d8a3SJacky Wang             "import dagger.Module;",
194*f585d8a3SJacky Wang             "import dagger.Provides;",
195*f585d8a3SJacky Wang             "import dagger.multibindings.IntoSet;",
196*f585d8a3SJacky Wang             "import dagger.multibindings.StringKey;",
197*f585d8a3SJacky Wang             "",
198*f585d8a3SJacky Wang             "@Module",
199*f585d8a3SJacky Wang             "class ParentModule {",
200*f585d8a3SJacky Wang             "  @Provides @IntoSet static Object parentObject() {",
201*f585d8a3SJacky Wang             "    return \"parent object\";",
202*f585d8a3SJacky Wang             "  }",
203*f585d8a3SJacky Wang             "}");
204*f585d8a3SJacky Wang     JavaFileObject child =
205*f585d8a3SJacky Wang         JavaFileObjects.forSourceLines(
206*f585d8a3SJacky Wang             "test.Child",
207*f585d8a3SJacky Wang             "package test;",
208*f585d8a3SJacky Wang             "",
209*f585d8a3SJacky Wang             "import dagger.Subcomponent;",
210*f585d8a3SJacky Wang             "import java.util.Set;",
211*f585d8a3SJacky Wang             "",
212*f585d8a3SJacky Wang             "@Subcomponent",
213*f585d8a3SJacky Wang             "interface Child {",
214*f585d8a3SJacky Wang             "  Set<Object> objectSet();",
215*f585d8a3SJacky Wang             "}");
216*f585d8a3SJacky Wang 
217*f585d8a3SJacky Wang     Compilation compilation = daggerCompilerWithoutGuava().compile(parent, parentModule, child);
218*f585d8a3SJacky Wang     assertThat(compilation).succeeded();
219*f585d8a3SJacky Wang     assertThat(compilation)
220*f585d8a3SJacky Wang         .generatedSourceFile("test.DaggerParent")
221*f585d8a3SJacky Wang         .hasSourceEquivalentTo(goldenFileRule.goldenFile("test.DaggerTestComponent"));
222*f585d8a3SJacky Wang   }
223*f585d8a3SJacky Wang 
daggerCompilerWithoutGuava()224*f585d8a3SJacky Wang   private Compiler daggerCompilerWithoutGuava() {
225*f585d8a3SJacky Wang     return compilerWithOptions(compilerMode.javacopts())
226*f585d8a3SJacky Wang         .withClasspath(CLASS_PATH_WITHOUT_GUAVA_OPTION);
227*f585d8a3SJacky Wang   }
228*f585d8a3SJacky Wang }
229