1 /* 2 * Copyright (C) 2015 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 dagger.internal.codegen.base.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER; 20 import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor; 21 22 import androidx.room.compiler.processing.util.Source; 23 import com.google.common.collect.ImmutableList; 24 import dagger.internal.codegen.binding.ErrorMessages; 25 import dagger.testing.compile.CompilerTests; 26 import dagger.testing.golden.GoldenFileRule; 27 import org.junit.Rule; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.Parameterized; 31 import org.junit.runners.Parameterized.Parameters; 32 33 /** Tests for {@link dagger.Subcomponent.Builder} validation. */ 34 @RunWith(Parameterized.class) 35 public class SubcomponentBuilderValidationTest { 36 @Parameters(name = "{0}") parameters()37 public static ImmutableList<Object[]> parameters() { 38 return CompilerMode.TEST_PARAMETERS; 39 } 40 41 @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule(); 42 43 private final CompilerMode compilerMode; 44 SubcomponentBuilderValidationTest(CompilerMode compilerMode)45 public SubcomponentBuilderValidationTest(CompilerMode compilerMode) { 46 this.compilerMode = compilerMode; 47 } 48 49 private static final ErrorMessages.ComponentCreatorMessages MSGS = 50 creatorMessagesFor(SUBCOMPONENT_BUILDER); 51 52 @Test testMoreThanOneArgFails()53 public void testMoreThanOneArgFails() { 54 Source childComponentFile = CompilerTests.javaSource("test.ChildComponent", 55 "package test;", 56 "", 57 "import dagger.Subcomponent;", 58 "", 59 "@Subcomponent", 60 "abstract class ChildComponent {", 61 " @Subcomponent.Builder", 62 " interface Builder {", 63 " ChildComponent build();", 64 " Builder set(String s, Integer i);", 65 " Builder set(Number n, Double d);", 66 " }", 67 "}"); 68 69 CompilerTests.daggerCompiler(childComponentFile) 70 .withProcessingOptions(compilerMode.processorOptions()) 71 .compile( 72 subject -> { 73 subject.hasErrorCount(2); 74 subject 75 .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg()) 76 .onSource(childComponentFile) 77 .onLine(10); 78 subject 79 .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg()) 80 .onSource(childComponentFile) 81 .onLine(11); 82 }); 83 } 84 85 @Test testInheritedMoreThanOneArgFails()86 public void testInheritedMoreThanOneArgFails() { 87 Source childComponentFile = CompilerTests.javaSource("test.ChildComponent", 88 "package test;", 89 "", 90 "import dagger.Subcomponent;", 91 "", 92 "@Subcomponent", 93 "abstract class ChildComponent {", 94 " interface Parent {", 95 " ChildComponent build();", 96 " Builder set1(String s, Integer i);", 97 " }", 98 "", 99 " @Subcomponent.Builder", 100 " interface Builder extends Parent {}", 101 "}"); 102 103 String expectedErrorMsg = 104 String.format( 105 MSGS.inheritedSetterMethodsMustTakeOneArg(), 106 "test.ChildComponent.Builder test.ChildComponent.Parent.set1(String, Integer)"); 107 CompilerTests.daggerCompiler(childComponentFile) 108 .withProcessingOptions(compilerMode.processorOptions()) 109 .compile( 110 subject -> { 111 subject.hasErrorCount(1); 112 subject 113 .hasErrorContaining(expectedErrorMsg) 114 .onSource(childComponentFile) 115 .onLine(13); 116 }); 117 } 118 119 @Test testSetterReturningNonVoidOrBuilderFails()120 public void testSetterReturningNonVoidOrBuilderFails() { 121 Source childComponentFile = CompilerTests.javaSource("test.ChildComponent", 122 "package test;", 123 "", 124 "import dagger.Subcomponent;", 125 "", 126 "@Subcomponent", 127 "abstract class ChildComponent {", 128 " @Subcomponent.Builder", 129 " interface Builder {", 130 " ChildComponent build();", 131 " String set(Integer i);", 132 " }", 133 "}"); 134 135 CompilerTests.daggerCompiler(childComponentFile) 136 .withProcessingOptions(compilerMode.processorOptions()) 137 .compile( 138 subject -> { 139 subject.hasErrorCount(1); 140 subject 141 .hasErrorContaining(MSGS.setterMethodsMustReturnVoidOrBuilder()) 142 .onSource(childComponentFile) 143 .onLine(10); 144 }); 145 } 146 147 @Test testInheritedSetterReturningNonVoidOrBuilderFails()148 public void testInheritedSetterReturningNonVoidOrBuilderFails() { 149 Source childComponentFile = CompilerTests.javaSource("test.ChildComponent", 150 "package test;", 151 "", 152 "import dagger.Subcomponent;", 153 "", 154 "@Subcomponent", 155 "abstract class ChildComponent {", 156 " interface Parent {", 157 " ChildComponent build();", 158 " String set(Integer i);", 159 " }", 160 "", 161 " @Subcomponent.Builder", 162 " interface Builder extends Parent {}", 163 "}"); 164 165 CompilerTests.daggerCompiler(childComponentFile) 166 .withProcessingOptions(compilerMode.processorOptions()) 167 .compile( 168 subject -> { 169 subject.hasErrorCount(1); 170 subject 171 .hasErrorContaining( 172 String.format( 173 MSGS.inheritedSetterMethodsMustReturnVoidOrBuilder(), 174 "String test.ChildComponent.Parent.set(Integer)")) 175 .onSource(childComponentFile) 176 .onLine(13); 177 }); 178 } 179 180 @Test testGenericsOnSetterMethodFails()181 public void testGenericsOnSetterMethodFails() { 182 Source childComponentFile = CompilerTests.javaSource("test.ChildComponent", 183 "package test;", 184 "", 185 "import dagger.Subcomponent;", 186 "", 187 "@Subcomponent", 188 "abstract class ChildComponent {", 189 " @Subcomponent.Builder", 190 " interface Builder {", 191 " ChildComponent build();", 192 " <T> Builder set(T t);", 193 " }", 194 "}"); 195 196 CompilerTests.daggerCompiler(childComponentFile) 197 .withProcessingOptions(compilerMode.processorOptions()) 198 .compile( 199 subject -> { 200 subject.hasErrorCount(1); 201 subject 202 .hasErrorContaining(MSGS.methodsMayNotHaveTypeParameters()) 203 .onSource(childComponentFile) 204 .onLine(10); 205 }); 206 } 207 208 @Test testGenericsOnInheritedSetterMethodFails()209 public void testGenericsOnInheritedSetterMethodFails() { 210 Source childComponentFile = CompilerTests.javaSource("test.ChildComponent", 211 "package test;", 212 "", 213 "import dagger.Subcomponent;", 214 "", 215 "@Subcomponent", 216 "abstract class ChildComponent {", 217 " interface Parent {", 218 " ChildComponent build();", 219 " <T> Builder set(T t);", 220 " }", 221 "", 222 " @Subcomponent.Builder", 223 " interface Builder extends Parent {}", 224 "}"); 225 226 CompilerTests.daggerCompiler(childComponentFile) 227 .withProcessingOptions(compilerMode.processorOptions()) 228 .compile( 229 subject -> { 230 subject.hasErrorCount(1); 231 subject 232 .hasErrorContaining( 233 String.format( 234 MSGS.inheritedMethodsMayNotHaveTypeParameters(), 235 "test.ChildComponent.Builder test.ChildComponent.Parent.set(T)")) 236 .onSource(childComponentFile) 237 .onLine(13); 238 }); 239 } 240 } 241