View Javadoc
1   package org.codehaus.plexus.compiler.javac;
2   
3   /**
4    * The MIT License
5    *
6    * Copyright (c) 2005, The Codehaus
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  import java.io.File;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Collection;
30  import java.util.LinkedHashMap;
31  import java.util.List;
32  import java.util.Map;
33  
34  import org.codehaus.plexus.compiler.AbstractCompilerTest;
35  import org.codehaus.plexus.compiler.CompilerConfiguration;
36  import org.codehaus.plexus.util.StringUtils;
37  import org.junit.jupiter.api.BeforeEach;
38  import org.junit.jupiter.api.Test;
39  
40  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
41  
42  /**
43   * @author <a href="mailto:jason@plexus.org">Jason van Zyl</a>
44   */
45  public abstract class AbstractJavacCompilerTest extends AbstractCompilerTest {
46      private static final String PS = File.pathSeparator;
47  
48      @BeforeEach
49      public void setUp() {
50          setCompilerDebug(true);
51          setCompilerDeprecationWarnings(true);
52      }
53  
54      @Override
55      protected String getRoleHint() {
56          return "javac";
57      }
58  
59      @Override
60      protected int expectedErrors() {
61          String javaVersion = getJavaVersion();
62          if (javaVersion.contains("9.0")
63                  || javaVersion.contains("11")
64                  || javaVersion.contains("14")
65                  || javaVersion.contains("15")
66                  || javaVersion.contains("16")
67                  || javaVersion.contains("17")
68                  || javaVersion.contains("18")
69                  || javaVersion.contains("19")
70                  || javaVersion.contains("20")
71                  || javaVersion.contains("21")) {
72              return 5;
73          }
74          // javac output changed for misspelled modifiers starting in 1.6...they now generate 2 errors per occurrence,
75          // not one.
76          if ("1.5".compareTo(javaVersion) < 0) {
77              return 4;
78          } else {
79              return 3;
80          }
81      }
82  
83      @Override
84      protected int expectedWarnings() {
85          String javaVersion = getJavaVersion();
86          if (javaVersion.contains("9.0")
87                  || javaVersion.contains("11")
88                  || javaVersion.contains("14")
89                  || javaVersion.contains("15")
90                  || javaVersion.contains("16")
91                  || javaVersion.contains("17")
92                  || javaVersion.contains("18")
93                  || javaVersion.contains("19")
94                  || javaVersion.contains("20")
95                  || javaVersion.contains("21")) {
96              return 1;
97          }
98          if (javaVersion.contains("1.8")) {
99              // lots of new warnings about obsoletions for future releases
100             return 30;
101         }
102 
103         if ("1.6".compareTo(javaVersion) < 0) {
104             // with 1.7 some warning with bootstrap class path not set in conjunction with -source 1.3
105             return 9;
106         }
107 
108         return 2;
109     }
110 
111     @Override
112     public String getTargetVersion() {
113         String javaVersion = getJavaVersion();
114         if (javaVersion.contains("9.0")) {
115             return "1.7";
116         }
117         if (javaVersion.contains("11")) {
118             return "11";
119         }
120         if (javaVersion.contains("14")) {
121             return "14";
122         }
123         if (javaVersion.contains("15")) {
124             return "15";
125         }
126         if (javaVersion.contains("16")) {
127             return "16";
128         }
129         if (javaVersion.contains("17")) {
130             return "17";
131         }
132         if (javaVersion.contains("18")) {
133             return "18";
134         }
135         if (javaVersion.contains("19")) {
136             return "19";
137         }
138         if (javaVersion.contains("20")) {
139             return "20";
140         }
141         if (javaVersion.contains("21")) {
142             return "21";
143         }
144         return super.getTargetVersion();
145     }
146 
147     @Override
148     public String getSourceVersion() {
149         String javaVersion = getJavaVersion();
150         if (javaVersion.contains("9.0")) {
151             return "1.7";
152         }
153         if (javaVersion.contains("11")) {
154             return "11";
155         }
156         if (javaVersion.contains("14")) {
157             return "14";
158         }
159         if (javaVersion.contains("15")) {
160             return "15";
161         }
162         if (javaVersion.contains("16")) {
163             return "16";
164         }
165         if (javaVersion.contains("17")) {
166             return "17";
167         }
168         if (javaVersion.contains("18")) {
169             return "18";
170         }
171         if (javaVersion.contains("19")) {
172             return "19";
173         }
174         if (javaVersion.contains("20")) {
175             return "20";
176         }
177         if (javaVersion.contains("21")) {
178             return "21";
179         }
180         return super.getTargetVersion();
181     }
182 
183     @Override
184     protected Collection<String> expectedOutputFiles() {
185         String javaVersion = getJavaVersion();
186         if (javaVersion.contains("9.0")
187                 || javaVersion.contains("11")
188                 || javaVersion.contains("14")
189                 || javaVersion.contains("15")
190                 || javaVersion.contains("16")
191                 || javaVersion.contains("17")
192                 || javaVersion.contains("18")
193                 || javaVersion.contains("19")
194                 || javaVersion.contains("20")
195                 || javaVersion.contains("21")) {
196             return Arrays.asList(
197                     "org/codehaus/foo/Deprecation.class",
198                     "org/codehaus/foo/ExternalDeps.class",
199                     "org/codehaus/foo/Person.class");
200         }
201         return Arrays.asList(
202                 "org/codehaus/foo/Deprecation.class",
203                 "org/codehaus/foo/ExternalDeps.class",
204                 "org/codehaus/foo/Person.class",
205                 "org/codehaus/foo/ReservedWord.class");
206     }
207 
208     protected void internalTest(
209             CompilerConfiguration compilerConfiguration, List<String> expectedArguments, String javacVersion) {
210         internalTest(compilerConfiguration, expectedArguments, new String[0], javacVersion);
211     }
212 
213     public void internalTest(
214             CompilerConfiguration compilerConfiguration,
215             List<String> expectedArguments,
216             String[] sources,
217             String javacVersion) {
218         String[] actualArguments = JavacCompiler.buildCompilerArguments(compilerConfiguration, sources, javacVersion);
219 
220         assertArrayEquals(actualArguments, expectedArguments.toArray(new String[0]));
221     }
222 
223     @Test
224     public void testBuildCompilerArgs13() {
225         List<String> expectedArguments = new ArrayList<>();
226 
227         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
228 
229         populateArguments(compilerConfiguration, expectedArguments, true, true, false);
230 
231         internalTest(compilerConfiguration, expectedArguments, "1.3");
232     }
233 
234     @Test
235     public void testBuildCompilerArgs14() {
236         List<String> expectedArguments = new ArrayList<>();
237 
238         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
239 
240         populateArguments(compilerConfiguration, expectedArguments, false, false, false);
241 
242         internalTest(compilerConfiguration, expectedArguments, "1.4");
243     }
244 
245     @Test
246     public void testBuildCompilerArgs15() {
247         List<String> expectedArguments = new ArrayList<>();
248 
249         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
250 
251         populateArguments(compilerConfiguration, expectedArguments, false, false, false);
252 
253         internalTest(compilerConfiguration, expectedArguments, "1.5");
254     }
255 
256     @Test
257     public void testBuildCompilerArgs18() {
258         List<String> expectedArguments = new ArrayList<>();
259 
260         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
261 
262         populateArguments(compilerConfiguration, expectedArguments, false, false, true);
263 
264         internalTest(compilerConfiguration, expectedArguments, "1.8");
265     }
266 
267     @Test
268     public void testBuildCompilerArgsUnspecifiedVersion() {
269         List<String> expectedArguments = new ArrayList<>();
270 
271         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
272 
273         populateArguments(compilerConfiguration, expectedArguments, false, false, true);
274 
275         internalTest(compilerConfiguration, expectedArguments, "unknown");
276     }
277 
278     @Test
279     public void testBuildCompilerDebugLevel() {
280         List<String> expectedArguments = new ArrayList<>();
281 
282         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
283 
284         compilerConfiguration.setDebug(true);
285 
286         compilerConfiguration.setDebugLevel("none");
287 
288         populateArguments(compilerConfiguration, expectedArguments, false, false, true);
289 
290         internalTest(compilerConfiguration, expectedArguments, "1.8");
291     }
292 
293     // PLXCOMP-190
294     @Test
295     public void testJRuntimeArguments() {
296         List<String> expectedArguments = new ArrayList<>();
297 
298         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
299 
300         // outputLocation
301         compilerConfiguration.setOutputLocation("/output");
302         expectedArguments.add("-d");
303         expectedArguments.add(new File("/output").getAbsolutePath());
304 
305         // targetVersion
306         compilerConfiguration.setTargetVersion("1.3");
307         expectedArguments.add("-target");
308         expectedArguments.add("1.3");
309 
310         // sourceVersion
311         compilerConfiguration.setSourceVersion("1.3");
312         expectedArguments.add("-source");
313         expectedArguments.add("1.3");
314 
315         // unshared table
316         expectedArguments.add("-XDuseUnsharedTable=true");
317 
318         // customCompilerArguments
319         Map<String, String> customCompilerArguments = new LinkedHashMap<>();
320         customCompilerArguments.put("-J-Duser.language=en_us", null);
321         compilerConfiguration.setCustomCompilerArgumentsAsMap(customCompilerArguments);
322         // don't expect this argument!!
323 
324         internalTest(compilerConfiguration, expectedArguments, "1.8");
325     }
326 
327     @Test
328     public void testModulePathAnnotations() throws Exception {
329         List<String> expectedArguments = new ArrayList<>();
330 
331         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
332 
333         final String[] source = {"module-info.java"};
334 
335         // outputLocation
336         compilerConfiguration.setOutputLocation("/output");
337         expectedArguments.add("-d");
338         expectedArguments.add(new File("/output").getAbsolutePath());
339 
340         // failOnWarning
341         compilerConfiguration.setModulepathEntries(Arrays.asList("/repo/a/b/1.0/b-1.0.jar", "/repo/c/d/1.0/d-1.0.jar"));
342         expectedArguments.add("--module-path");
343         expectedArguments.add(
344                 "/repo/a/b/1.0/b-1.0.jar" + File.pathSeparator + "/repo/c/d/1.0/d-1.0.jar" + File.pathSeparator);
345 
346         compilerConfiguration.setProcessorModulePathEntries(
347                 Arrays.asList("/repo/a/b/1.0/annotations-1.0.jar", "/repo/f/a/1.0/annotations-4.0.jar"));
348         expectedArguments.add("--processor-module-path");
349         expectedArguments.add("/repo/a/b/1.0/annotations-1.0.jar" + File.pathSeparator
350                 + "/repo/f/a/1.0/annotations-4.0.jar" + File.pathSeparator);
351 
352         // releaseVersion
353         compilerConfiguration.setReleaseVersion("9");
354         expectedArguments.add("--release");
355         expectedArguments.add("9");
356 
357         // unshared table
358         expectedArguments.add("-XDuseUnsharedTable=true");
359 
360         internalTest(compilerConfiguration, expectedArguments, source, "11.0.1");
361     }
362 
363     @Test
364     public void testModulePath() throws Exception {
365         List<String> expectedArguments = new ArrayList<>();
366 
367         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
368 
369         // outputLocation
370         compilerConfiguration.setOutputLocation("/output");
371         expectedArguments.add("-d");
372         expectedArguments.add(new File("/output").getAbsolutePath());
373 
374         // failOnWarning
375         compilerConfiguration.setModulepathEntries(Arrays.asList("/repo/a/b/1.0/b-1.0.jar", "/repo/c/d/1.0/d-1.0.jar"));
376         expectedArguments.add("--module-path");
377         expectedArguments.add(
378                 "/repo/a/b/1.0/b-1.0.jar" + File.pathSeparator + "/repo/c/d/1.0/d-1.0.jar" + File.pathSeparator);
379 
380         // default source + target
381         expectedArguments.add("-target");
382         expectedArguments.add("1.1");
383         expectedArguments.add("-source");
384         expectedArguments.add("1.3");
385 
386         // unshared table
387         expectedArguments.add("-XDuseUnsharedTable=true");
388 
389         internalTest(compilerConfiguration, expectedArguments, "11.0.1");
390     }
391 
392     @Test
393     public void testModuleVersion() {
394         List<String> expectedArguments = new ArrayList<>();
395 
396         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
397 
398         // outputLocation
399         compilerConfiguration.setOutputLocation("/output");
400         expectedArguments.add("-d");
401         expectedArguments.add(new File("/output").getAbsolutePath());
402 
403         // default source + target
404         expectedArguments.add("-target");
405         expectedArguments.add("1.1");
406         expectedArguments.add("-source");
407         expectedArguments.add("1.3");
408 
409         // module version
410         compilerConfiguration.setModuleVersion("1.2.0-SNAPSHOT");
411         expectedArguments.add("--module-version");
412         expectedArguments.add("1.2.0-SNAPSHOT");
413 
414         // unshared table
415         expectedArguments.add("-XDuseUnsharedTable=true");
416 
417         internalTest(compilerConfiguration, expectedArguments, "11.0.1");
418     }
419 
420     @Test
421     public void testReleaseVersion() {
422         List<String> expectedArguments = new ArrayList<>();
423 
424         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
425 
426         // outputLocation
427         compilerConfiguration.setOutputLocation("/output");
428         expectedArguments.add("-d");
429         expectedArguments.add(new File("/output").getAbsolutePath());
430 
431         // releaseVersion
432         compilerConfiguration.setReleaseVersion("6");
433         expectedArguments.add("--release");
434         expectedArguments.add("6");
435 
436         // unshared table
437         expectedArguments.add("-XDuseUnsharedTable=true");
438 
439         internalTest(compilerConfiguration, expectedArguments, "11.0.1");
440     }
441 
442     @Test
443     public void testFailOnWarning() {
444         List<String> expectedArguments = new ArrayList<>();
445 
446         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
447 
448         // outputLocation
449         compilerConfiguration.setOutputLocation("/output");
450         expectedArguments.add("-d");
451         expectedArguments.add(new File("/output").getAbsolutePath());
452 
453         // failOnWarning
454         compilerConfiguration.setFailOnWarning(true);
455         expectedArguments.add("-Werror");
456 
457         // default source + target
458         expectedArguments.add("-target");
459         expectedArguments.add("1.1");
460         expectedArguments.add("-source");
461         expectedArguments.add("1.3");
462 
463         // unshared table
464         expectedArguments.add("-XDuseUnsharedTable=true");
465 
466         internalTest(compilerConfiguration, expectedArguments, "1.8");
467     }
468 
469     @Test
470     public void testMultipleAddExports() {
471         List<String> expectedArguments = new ArrayList<>();
472 
473         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
474 
475         // outputLocation
476         compilerConfiguration.setOutputLocation("/output");
477         expectedArguments.add("-d");
478         expectedArguments.add(new File("/output").getAbsolutePath());
479 
480         // default source + target
481         expectedArguments.add("-target");
482         expectedArguments.add("1.1");
483         expectedArguments.add("-source");
484         expectedArguments.add("1.3");
485 
486         // add multiple --add-exports
487         compilerConfiguration.addCompilerCustomArgument("--add-exports", "FROM-MOD/package1=OTHER-MOD");
488         expectedArguments.add("--add-exports");
489         expectedArguments.add("FROM-MOD/package1=OTHER-MOD");
490         compilerConfiguration.addCompilerCustomArgument("--add-exports", "FROM-MOD/package2=OTHER-MOD");
491         expectedArguments.add("--add-exports");
492         expectedArguments.add("FROM-MOD/package2=OTHER-MOD");
493 
494         // unshared table
495         expectedArguments.add("-XDuseUnsharedTable=true");
496 
497         internalTest(compilerConfiguration, expectedArguments, "1.8");
498     }
499 
500     @Test
501     public void testWithGivenUnsharedTable() {
502         List<String> expectedArguments = new ArrayList<>();
503 
504         CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
505 
506         // outputLocation
507         compilerConfiguration.setOutputLocation("/output");
508         expectedArguments.add("-d");
509         expectedArguments.add(new File("/output").getAbsolutePath());
510 
511         // releaseVersion
512         compilerConfiguration.setReleaseVersion("6");
513         expectedArguments.add("--release");
514         expectedArguments.add("6");
515 
516         // unshared table
517         compilerConfiguration.addCompilerCustomArgument("-XDuseUnsharedTable=false", null);
518         expectedArguments.add("-XDuseUnsharedTable=false");
519 
520         internalTest(compilerConfiguration, expectedArguments, "11.0.1");
521     }
522 
523     /* This test fails on Java 1.4. The multiple parameters of the same source file cause an error, as it is interpreted as a DuplicateClass
524      * Setting the size of the array to 3 is fine, but does not exactly test what it is supposed to - disabling the test for now
525     public void testCommandLineTooLongWhenForking()
526         throws Exception
527     {
528         JavacCompiler compiler = (JavacCompiler) lookup( org.codehaus.plexus.compiler.Compiler.ROLE, getRoleHint() );
529 
530         File destDir = new File( "target/test-classes-cmd" );
531         destDir.mkdirs();
532 
533         // fill the cmd line arguments, 300 is enough to make it break
534         String[] args = new String[400];
535         args[0] = "-d";
536         args[1] = destDir.getAbsolutePath();
537         for ( int i = 2; i < args.length; i++ )
538         {
539             args[i] = "org/codehaus/foo/Person.java";
540         }
541 
542         CompilerConfiguration config = new CompilerConfiguration();
543         config.setWorkingDirectory( new File( getBasedir() + "/src/test-input/src/main" ) );
544         config.setFork( true );
545 
546         List messages = compiler.compileOutOfProcess( config, "javac", args );
547 
548         assertEquals( "There were errors launching the external compiler: " + messages, 0, messages.size() );
549     }
550     */
551 
552     private void populateArguments(
553             CompilerConfiguration compilerConfiguration,
554             List<String> expectedArguments,
555             boolean suppressSourceVersion,
556             boolean suppressEncoding,
557             boolean parameters) {
558         // outputLocation
559 
560         compilerConfiguration.setOutputLocation("/output");
561 
562         expectedArguments.add("-d");
563 
564         expectedArguments.add(new File("/output").getAbsolutePath());
565 
566         // classpathEntires
567 
568         List<String> classpathEntries = new ArrayList<>();
569 
570         classpathEntries.add("/myjar1.jar");
571 
572         classpathEntries.add("/myjar2.jar");
573 
574         compilerConfiguration.setClasspathEntries(classpathEntries);
575 
576         expectedArguments.add("-classpath");
577 
578         expectedArguments.add("/myjar1.jar" + PS + "/myjar2.jar" + PS);
579 
580         // sourceRoots
581 
582         List<String> compileSourceRoots = new ArrayList<>();
583 
584         compileSourceRoots.add("/src/main/one");
585 
586         compileSourceRoots.add("/src/main/two");
587 
588         compilerConfiguration.setSourceLocations(compileSourceRoots);
589 
590         expectedArguments.add("-sourcepath");
591 
592         expectedArguments.add("/src/main/one" + PS + "/src/main/two" + PS);
593 
594         // debug
595 
596         compilerConfiguration.setDebug(true);
597 
598         if (StringUtils.isNotEmpty(compilerConfiguration.getDebugLevel())) {
599             expectedArguments.add("-g:" + compilerConfiguration.getDebugLevel());
600         } else {
601             expectedArguments.add("-g");
602         }
603 
604         // parameters
605 
606         compilerConfiguration.setParameters(true);
607 
608         if (parameters) {
609             expectedArguments.add("-parameters");
610         }
611 
612         // showDeprecation
613 
614         compilerConfiguration.setShowDeprecation(true);
615 
616         expectedArguments.add("-deprecation");
617 
618         // targetVersion
619 
620         compilerConfiguration.setTargetVersion("1.3");
621 
622         expectedArguments.add("-target");
623 
624         expectedArguments.add("1.3");
625 
626         // sourceVersion
627 
628         compilerConfiguration.setSourceVersion("1.3");
629 
630         if (!suppressSourceVersion) {
631             expectedArguments.add("-source");
632 
633             expectedArguments.add("1.3");
634         }
635 
636         // sourceEncoding
637 
638         compilerConfiguration.setSourceEncoding("iso-8859-1");
639 
640         if (!suppressEncoding) {
641             expectedArguments.add("-encoding");
642 
643             expectedArguments.add("iso-8859-1");
644         }
645 
646         // customerCompilerArguments
647 
648         Map<String, String> customerCompilerArguments = new LinkedHashMap<>();
649 
650         customerCompilerArguments.put("arg1", null);
651 
652         customerCompilerArguments.put("foo", "bar");
653 
654         compilerConfiguration.setCustomCompilerArgumentsAsMap(customerCompilerArguments);
655 
656         expectedArguments.add("arg1");
657 
658         expectedArguments.add("foo");
659 
660         expectedArguments.add("bar");
661 
662         expectedArguments.add("-XDuseUnsharedTable=true");
663     }
664 }