1 /* 2 * Copyright 2016 Google Inc. All Rights Reserved. 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 com.google.turbine.options; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth8.assertThat; 21 import static org.junit.Assert.assertThrows; 22 import static org.junit.Assert.fail; 23 24 import com.google.common.collect.ImmutableList; 25 import com.google.common.collect.Iterables; 26 import com.google.turbine.options.TurbineOptions.ReducedClasspathMode; 27 import java.nio.charset.StandardCharsets; 28 import java.nio.file.Files; 29 import java.nio.file.Path; 30 import java.util.Arrays; 31 import org.junit.Rule; 32 import org.junit.Test; 33 import org.junit.rules.TemporaryFolder; 34 import org.junit.runner.RunWith; 35 import org.junit.runners.JUnit4; 36 37 @RunWith(JUnit4.class) 38 public class TurbineOptionsTest { 39 40 @Rule public final TemporaryFolder tmpFolder = new TemporaryFolder(); 41 42 static final ImmutableList<String> BASE_ARGS = 43 ImmutableList.of("--output", "out.jar", "--target_label", "//java/com/google/test"); 44 45 @Test exhaustiveArgs()46 public void exhaustiveArgs() throws Exception { 47 String[] lines = { 48 "--output", 49 "out.jar", 50 "--source_jars", 51 "sources1.srcjar", 52 "sources2.srcjar", 53 "--processors", 54 "com.foo.MyProcessor", 55 "com.foo.OtherProcessor", 56 "--processorpath", 57 "libproc1.jar", 58 "libproc2.jar", 59 "--classpath", 60 "lib1.jar", 61 "lib2.jar", 62 "--bootclasspath", 63 "rt.jar", 64 "zipfs.jar", 65 "--javacopts", 66 "-source", 67 "8", 68 "-target", 69 "8", 70 "--", 71 "--sources", 72 "Source1.java", 73 "Source2.java", 74 "--output_deps", 75 "out.jdeps", 76 "--target_label", 77 "//java/com/google/test", 78 "--injecting_rule_kind", 79 "foo_library", 80 }; 81 82 TurbineOptions options = 83 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 84 85 assertThat(options.output()).hasValue("out.jar"); 86 assertThat(options.sourceJars()) 87 .containsExactly("sources1.srcjar", "sources2.srcjar") 88 .inOrder(); 89 assertThat(options.processors()) 90 .containsExactly("com.foo.MyProcessor", "com.foo.OtherProcessor") 91 .inOrder(); 92 assertThat(options.processorPath()).containsExactly("libproc1.jar", "libproc2.jar").inOrder(); 93 assertThat(options.classPath()).containsExactly("lib1.jar", "lib2.jar").inOrder(); 94 assertThat(options.bootClassPath()).containsExactly("rt.jar", "zipfs.jar").inOrder(); 95 assertThat(options.javacOpts()).containsExactly("-source", "8", "-target", "8").inOrder(); 96 assertThat(options.sources()).containsExactly("Source1.java", "Source2.java"); 97 assertThat(options.outputDeps()).hasValue("out.jdeps"); 98 assertThat(options.targetLabel()).hasValue("//java/com/google/test"); 99 assertThat(options.injectingRuleKind()).hasValue("foo_library"); 100 assertThat(options.reducedClasspathMode()).isEqualTo(ReducedClasspathMode.NONE); 101 } 102 103 @Test strictJavaDepsArgs()104 public void strictJavaDepsArgs() throws Exception { 105 String[] lines = { 106 "--classpath", 107 "blaze-out/foo/libbar.jar", 108 "blaze-out/foo/libbaz1.jar", 109 "blaze-out/foo/libbaz2.jar", 110 "blaze-out/proto/libproto.jar", 111 "--direct_dependencies", 112 "blaze-out/foo/libbar.jar", 113 "--deps_artifacts", 114 "foo.jdeps", 115 "bar.jdeps", 116 "", 117 }; 118 119 TurbineOptions options = 120 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 121 122 assertThat(options.targetLabel()).hasValue("//java/com/google/test"); 123 assertThat(options.directJars()).containsExactly("blaze-out/foo/libbar.jar"); 124 assertThat(options.depsArtifacts()).containsExactly("foo.jdeps", "bar.jdeps"); 125 } 126 127 @Test classpathArgs()128 public void classpathArgs() throws Exception { 129 String[] lines = { 130 "--classpath", 131 "liba.jar", 132 "libb.jar", 133 "libc.jar", 134 "--processorpath", 135 "libpa.jar", 136 "libpb.jar", 137 "libpc.jar", 138 }; 139 140 TurbineOptions options = 141 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 142 143 assertThat(options.classPath()).containsExactly("liba.jar", "libb.jar", "libc.jar").inOrder(); 144 assertThat(options.processorPath()) 145 .containsExactly("libpa.jar", "libpb.jar", "libpc.jar") 146 .inOrder(); 147 } 148 149 @Test repeatedClasspath()150 public void repeatedClasspath() throws Exception { 151 String[] lines = { 152 "--classpath", 153 "liba.jar", 154 "libb.jar", 155 "libc.jar", 156 "--processorpath", 157 "libpa.jar", 158 "libpb.jar", 159 "libpc.jar", 160 }; 161 162 TurbineOptions options = 163 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 164 165 assertThat(options.classPath()).containsExactly("liba.jar", "libb.jar", "libc.jar").inOrder(); 166 assertThat(options.processorPath()) 167 .containsExactly("libpa.jar", "libpb.jar", "libpc.jar") 168 .inOrder(); 169 } 170 171 @Test optionalTargetLabel()172 public void optionalTargetLabel() throws Exception { 173 String[] lines = { 174 "--output", 175 "out.jar", 176 "--classpath", 177 "liba.jar", 178 "libb.jar", 179 "libc.jar", 180 "--processorpath", 181 "libpa.jar", 182 "libpb.jar", 183 "libpc.jar", 184 }; 185 186 TurbineOptions options = TurbineOptionsParser.parse(Arrays.asList(lines)); 187 188 assertThat(options.targetLabel()).isEmpty(); 189 assertThat(options.injectingRuleKind()).isEmpty(); 190 } 191 192 @Test paramsFile()193 public void paramsFile() throws Exception { 194 Iterable<String> paramsArgs = 195 Iterables.concat( 196 BASE_ARGS, Arrays.asList("--javacopts", "-source", "8", "-target", "8", "--")); 197 Path params = tmpFolder.newFile("params.txt").toPath(); 198 Files.write(params, paramsArgs, StandardCharsets.UTF_8); 199 200 // @ is a prefix for external repository targets, and the prefix for params files. Targets 201 // are disambiguated by prepending an extra @. 202 String[] lines = { 203 "@" + params.toAbsolutePath(), "--target_label", "//custom/label", 204 }; 205 206 TurbineOptions options = TurbineOptionsParser.parse(Arrays.asList(lines)); 207 208 // assert that options were read from params file 209 assertThat(options.javacOpts()).containsExactly("-source", "8", "-target", "8").inOrder(); 210 // ... and directly from the command line 211 assertThat(options.targetLabel()).hasValue("//custom/label"); 212 } 213 214 @Test escapedExternalRepositoryLabel()215 public void escapedExternalRepositoryLabel() throws Exception { 216 // @ is a prefix for external repository targets, and the prefix for params files. Targets 217 // are disambiguated by prepending an extra @. 218 String[] lines = { 219 "--target_label", "@@other-repo//foo:local-jam", 220 }; 221 222 TurbineOptions options = 223 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 224 225 assertThat(options.targetLabel()).hasValue("@other-repo//foo:local-jam"); 226 } 227 228 @Test tolerateMissingOutput()229 public void tolerateMissingOutput() throws Exception { 230 TurbineOptions options = TurbineOptions.builder().build(); 231 assertThat(options.output()).isEmpty(); 232 } 233 234 @Test paramsFileExists()235 public void paramsFileExists() throws Exception { 236 String[] lines = { 237 "@/NOSUCH", "--javacopts", "-source", "7", "--", 238 }; 239 AssertionError expected = null; 240 try { 241 TurbineOptionsParser.parse(Arrays.asList(lines)); 242 } catch (AssertionError e) { 243 expected = e; 244 } 245 if (expected == null) { 246 fail(); 247 } 248 assertThat(expected).hasMessageThat().contains("params file does not exist"); 249 } 250 251 @Test emptyParamsFiles()252 public void emptyParamsFiles() throws Exception { 253 Path params = tmpFolder.newFile("params.txt").toPath(); 254 Files.write(params, new byte[0]); 255 String[] lines = { 256 "--sources", "A.java", "@" + params.toAbsolutePath(), "B.java", 257 }; 258 TurbineOptions options = 259 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 260 assertThat(options.sources()).containsExactly("A.java", "B.java").inOrder(); 261 } 262 263 @Test javacopts()264 public void javacopts() throws Exception { 265 String[] lines = { 266 "--javacopts", 267 "--release", 268 "8", 269 "--", 270 "--sources", 271 "Test.java", 272 "--javacopts", 273 "--release", 274 "9", 275 "--", 276 }; 277 278 TurbineOptions options = 279 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 280 281 assertThat(options.javacOpts()).containsExactly("--release", "8", "--release", "9").inOrder(); 282 assertThat(options.sources()).containsExactly("Test.java"); 283 } 284 285 @Test unknownOption()286 public void unknownOption() throws Exception { 287 IllegalArgumentException e = 288 assertThrows( 289 IllegalArgumentException.class, 290 () -> 291 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList("--nosuch")))); 292 assertThat(e).hasMessageThat().contains("unknown option"); 293 } 294 295 @Test unterminatedJavacopts()296 public void unterminatedJavacopts() throws Exception { 297 IllegalArgumentException e = 298 assertThrows( 299 IllegalArgumentException.class, 300 () -> 301 TurbineOptionsParser.parse( 302 Iterables.concat(BASE_ARGS, Arrays.asList("--javacopts", "--release", "8")))); 303 assertThat(e).hasMessageThat().contains("javacopts should be terminated by `--`"); 304 } 305 306 @Test miscOutputs()307 public void miscOutputs() throws Exception { 308 TurbineOptions options = 309 TurbineOptionsParser.parse( 310 Iterables.concat( 311 BASE_ARGS, 312 ImmutableList.of("--gensrc_output", "gensrc.jar", "--profile", "turbine.prof"))); 313 assertThat(options.gensrcOutput()).hasValue("gensrc.jar"); 314 assertThat(options.profile()).hasValue("turbine.prof"); 315 } 316 317 @Test unescape()318 public void unescape() throws Exception { 319 String[] lines = { 320 "--sources", "Test.java", "'Foo$Bar.java'", 321 }; 322 TurbineOptions options = 323 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 324 assertThat(options.sources()).containsExactly("Test.java", "Foo$Bar.java").inOrder(); 325 } 326 327 @Test invalidUnescape()328 public void invalidUnescape() throws Exception { 329 String[] lines = {"--sources", "'Foo$Bar.java"}; 330 assertThrows( 331 IllegalArgumentException.class, 332 () -> TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines)))); 333 } 334 335 @Test builtinProcessors()336 public void builtinProcessors() throws Exception { 337 String[] lines = {"--builtin_processors", "BuiltinProcessor"}; 338 TurbineOptions options = 339 TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); 340 assertThat(options.builtinProcessors()).containsExactly("BuiltinProcessor"); 341 } 342 343 @Test reducedClasspathMode()344 public void reducedClasspathMode() throws Exception { 345 for (ReducedClasspathMode mode : ReducedClasspathMode.values()) { 346 TurbineOptions options = 347 TurbineOptionsParser.parse( 348 Iterables.concat( 349 BASE_ARGS, ImmutableList.of("--reduce_classpath_mode", mode.name()))); 350 assertThat(options.reducedClasspathMode()).isEqualTo(mode); 351 } 352 } 353 354 @Test javaBuilderCompatibility()355 public void javaBuilderCompatibility() throws Exception { 356 TurbineOptions options = 357 TurbineOptionsParser.parse( 358 Iterables.concat( 359 BASE_ARGS, 360 ImmutableList.of( 361 "--output_deps_proto", 362 "output_deps.proto", 363 "--generated_sources_output", 364 "generated_sources.jar", 365 "--experimental_fix_deps_tool", 366 "ignored", 367 "--strict_java_deps", 368 "ignored", 369 "--native_header_output", 370 "ignored", 371 "--compress_jar"))); 372 assertThat(options.outputDeps()).hasValue("output_deps.proto"); 373 assertThat(options.gensrcOutput()).hasValue("generated_sources.jar"); 374 } 375 376 @Test requiredValue()377 public void requiredValue() throws Exception { 378 IllegalArgumentException e = 379 assertThrows( 380 IllegalArgumentException.class, 381 () -> 382 TurbineOptionsParser.parse( 383 Iterables.concat(BASE_ARGS, ImmutableList.of("--output", "--system")))); 384 assertThat(e).hasMessageThat().contains("missing required argument for: --output"); 385 } 386 } 387