• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 com.google.common.collect.ImmutableList;
21 import dagger.testing.compile.CompilerTests;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.junit.runners.Parameterized;
25 import org.junit.runners.Parameterized.Parameters;
26 
27 @RunWith(Parameterized.class)
28 public class OptionalBindingTest {
29   @Parameters(name = "{0}")
parameters()30   public static ImmutableList<Object[]> parameters() {
31     return CompilerMode.TEST_PARAMETERS;
32   }
33 
34   private final CompilerMode compilerMode;
35 
OptionalBindingTest(CompilerMode compilerMode)36   public OptionalBindingTest(CompilerMode compilerMode) {
37     this.compilerMode = compilerMode;
38   }
39 
40   @Test
provideExplicitOptionalInParent_AndBindsOptionalOfInChild()41   public void provideExplicitOptionalInParent_AndBindsOptionalOfInChild() {
42     Source parent =
43         CompilerTests.javaSource(
44             "test.Parent",
45             "package test;",
46             "",
47             "import dagger.Component;",
48             "import java.util.Optional;",
49             "",
50             "@Component(modules = ParentModule.class)",
51             "interface Parent {",
52             "  Optional<String> optional();",
53             "  Child child();",
54             "}");
55     Source parentModule =
56         CompilerTests.javaSource(
57             "test.ParentModule",
58             "package test;",
59             "",
60             "import dagger.Module;",
61             "import dagger.Provides;",
62             "import java.util.Optional;",
63             "",
64             "@Module",
65             "class ParentModule {",
66             "  @Provides",
67             "  Optional<String> optional() {",
68             "    return Optional.of(new String());",
69             "  }",
70             "}");
71 
72     Source child =
73         CompilerTests.javaSource(
74             "test.Child",
75             "package test;",
76             "",
77             "import dagger.Subcomponent;",
78             "import java.util.Optional;",
79             "",
80             "@Subcomponent(modules = ChildModule.class)",
81             "interface Child {",
82             "  Optional<String> optional();",
83             "}");
84     Source childModule =
85         CompilerTests.javaSource(
86             "test.ChildModule",
87             "package test;",
88             "",
89             "import dagger.BindsOptionalOf;",
90             "import dagger.Module;",
91             "",
92             "@Module",
93             "interface ChildModule {",
94             "  @BindsOptionalOf",
95             "  String optionalString();",
96             "}");
97 
98     CompilerTests.daggerCompiler(parent, parentModule, child, childModule)
99         .withProcessingOptions(compilerMode.processorOptions())
100         .compile(
101             subject -> {
102               subject.hasErrorCount(1);
103               subject.hasErrorContaining("Optional<String> is bound multiple times")
104                   .onSource(parent)
105                   .onLineContaining("interface Parent");
106             });
107   }
108 
109   // Note: This is a regression test for an issue we ran into in CL/644086367, where an optional
110   // binding owned by a parent component is also requested by a child component which declares an
111   // additional @BindsOptionalOf declaration. In this case, we just want to make sure that the setup
112   // builds successfully.
113   @Test
cachedInParent_succeeds()114   public void cachedInParent_succeeds() {
115     Source parent =
116         CompilerTests.javaSource(
117             "test.Parent",
118             "package test;",
119             "",
120             "import dagger.Component;",
121             "import java.util.Optional;",
122             "",
123             "@Component(modules = ParentModule.class)",
124             "interface Parent {",
125             "  Optional<String> optionalString();",
126             "  Child child();",
127             "}");
128     Source parentModule =
129         CompilerTests.javaSource(
130             "test.ParentModule",
131             "package test;",
132             "",
133             "import dagger.BindsOptionalOf;",
134             "import dagger.Module;",
135             "import dagger.Provides;",
136             "import java.util.Optional;",
137             "",
138             "@Module",
139             "interface ParentModule {",
140             "  @BindsOptionalOf",
141             "  String optionalParentString();",
142             "",
143             "  @Provides",
144             "  static String provideString() {",
145             "    return \"\";",
146             "  }",
147             "}");
148     Source child =
149         CompilerTests.javaSource(
150             "test.Child",
151             "package test;",
152             "",
153             "import dagger.Subcomponent;",
154             "import java.util.Optional;",
155             "",
156             "@Subcomponent(modules = ChildModule.class)",
157             "interface Child {",
158             "  Optional<String> optionalString();",
159             "}");
160     Source childModule =
161         CompilerTests.javaSource(
162             "test.ChildModule",
163             "package test;",
164             "",
165             "import dagger.BindsOptionalOf;",
166             "import dagger.Module;",
167             "",
168             "@Module",
169             "interface ChildModule {",
170             "  @BindsOptionalOf",
171             "  String optionalChildString();",
172             "}");
173 
174     CompilerTests.daggerCompiler(parent, parentModule, child, childModule)
175         .withProcessingOptions(compilerMode.processorOptions())
176         .compile(subject -> subject.hasErrorCount(0));
177   }
178 }
179