1 /*
2  * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 4981566 5028634 5094412 6304984 7025786 7025789 8001112 8028545 8000961 8030610 8028546 8188870 8173382 8173382
27  * @summary Check interpretation of -target and -source options
28  * @modules java.compiler
29  *          jdk.compiler
30  * @run main Versions
31  */
32 
33 import java.io.*;
34 import java.nio.*;
35 import java.nio.channels.*;
36 
37 import javax.tools.JavaCompiler;
38 import javax.tools.ToolProvider;
39 import javax.tools.JavaFileObject;
40 import javax.tools.StandardJavaFileManager;
41 import java.util.List;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 
45 
46 public class Versions {
47 
48     protected JavaCompiler javacompiler;
49     protected int failedCases;
50 
Versions()51     public Versions() throws IOException {
52         javacompiler = ToolProvider.getSystemJavaCompiler();
53         genSourceFiles();
54         failedCases = 0;
55     }
56 
main(String... args)57     public static void main(String... args) throws IOException {
58         Versions versions = new Versions();
59         versions.run();
60     }
61 
run()62     void run() {
63 
64         String TC = "";
65         System.out.println("Version.java: Starting");
66 
67         check("55.0");
68         check("55.0", "-source 1.6");
69         check("55.0", "-source 1.7");
70         check("55.0", "-source 1.8");
71         check("55.0", "-source 1.9");
72         check("55.0", "-source 1.10");
73         check("55.0", "-source 11");
74 
75         check_source_target(true, "50.0", "6", "6");
76         check_source_target(true, "51.0", "6", "7");
77         check_source_target(true, "51.0", "7", "7");
78         check_source_target(true, "52.0", "6", "8");
79         check_source_target(true, "52.0", "7", "8");
80         check_source_target(true, "52.0", "8", "8");
81         check_source_target(true, "53.0", "6", "9");
82         check_source_target(true, "53.0", "7", "9");
83         check_source_target(true, "53.0", "8", "9");
84         check_source_target(true, "53.0", "9", "9");
85         check_source_target(true, "54.0", "6", "10");
86         check_source_target(true, "54.0", "7", "10");
87         check_source_target(true, "54.0", "8", "10");
88         check_source_target(true, "54.0", "9", "10");
89         check_source_target(true, "54.0", "10", "10");
90         check_source_target(false, "55.0", "6", "11");
91         check_source_target(false, "55.0", "7", "11");
92         check_source_target(false, "55.0", "8", "11");
93         check_source_target(false, "55.0", "9", "11");
94         check_source_target(false, "55.0", "10", "11");
95         check_source_target(false, "55.0", "11", "11");
96 
97         checksrc16("-source 1.6");
98         checksrc16("-source 6");
99         checksrc16("-source 1.6", "-target 1.6");
100         checksrc16("-source 6", "-target 6");
101         checksrc17("-source 1.7");
102         checksrc17("-source 7");
103         checksrc17("-source 1.7", "-target 1.7");
104         checksrc17("-source 7", "-target 7");
105         checksrc18("-source 1.8");
106         checksrc18("-source 8");
107         checksrc18("-source 1.8", "-target 1.8");
108         checksrc18("-source 8", "-target 8");
109         checksrc19("-source 1.9");
110         checksrc19("-source 9");
111         checksrc19("-source 1.9", "-target 1.9");
112         checksrc19("-source 9", "-target 9");
113         checksrc110();
114         checksrc110("-source 1.10");
115         checksrc110("-source 10");
116         checksrc110("-source 1.10", "-target 1.10");
117         checksrc110("-source 10", "-target 10");
118         checksrc111("-source 11");
119         checksrc111("-source 11", "-target 11");
120         checksrc111("-target 11");
121 
122         fail("-source 7", "-target 1.6", "Base.java");
123         fail("-source 8", "-target 1.6", "Base.java");
124         fail("-source 8", "-target 1.7", "Base.java");
125         fail("-source 9", "-target 1.7", "Base.java");
126         fail("-source 9", "-target 1.8", "Base.java");
127         fail("-source 10", "-target 1.7", "Base.java");
128         fail("-source 10", "-target 1.8", "Base.java");
129         fail("-source 11", "-target 1.9", "Base.java");
130         fail("-source 11", "-target 1.10", "Base.java");
131 
132         fail("-source 1.5", "-target 1.5", "Base.java");
133         fail("-source 1.4", "-target 1.4", "Base.java");
134         fail("-source 1.3", "-target 1.3", "Base.java");
135         fail("-source 1.2", "-target 1.2", "Base.java");
136 
137         if (failedCases > 0) {
138             System.err.println("failedCases = " + String.valueOf(failedCases));
139             throw new Error("Test failed");
140         }
141 
142     }
143 
printargs(String fname,String... args)144     protected void printargs(String fname,String... args) {
145         System.out.printf("test: %s", fname);
146         for (String onearg : args) {
147             System.out.printf(" %s", onearg);
148         }
149         System.out.printf("\n", fname);
150     }
151 
check_source_target(boolean dotOne, String... args)152     protected void check_source_target(boolean dotOne, String... args) {
153         printargs("check_source_target", args);
154         check_target(dotOne, args[0], args[1], args[2]);
155         if (dotOne) {
156             check_target(dotOne, args[0], "1." + args[1], args[2]);
157         }
158     }
159 
check_target(boolean dotOne, String... args)160     protected void check_target(boolean dotOne, String... args) {
161         check(args[0], "-source " + args[1], "-target " + args[2]);
162         if (dotOne) {
163             check(args[0], "-source " + args[1], "-target 1." + args[2]);
164         }
165     }
166 
check(String major, String... args)167     protected void check(String major, String... args) {
168         printargs("check", args);
169         List<String> jcargs = new ArrayList<>();
170         jcargs.add("-Xlint:-options");
171 
172         // add in args conforming to List requrements of JavaCompiler
173         for (String onearg : args) {
174             String[] fields = onearg.split(" ");
175             for (String onefield : fields) {
176                 jcargs.add(onefield);
177             }
178         }
179 
180         boolean creturn = compile("Base.java", jcargs);
181         if (!creturn) {
182             // compilation errors note and return.. assume no class file
183             System.err.println("check: Compilation Failed");
184             System.err.println("\t classVersion:\t" + major);
185             System.err.println("\t arguments:\t" + jcargs);
186             failedCases++;
187 
188         } else if (!checkClassFileVersion("Base.class", major)) {
189             failedCases++;
190         }
191     }
192 
checksrc16(String... args)193     protected void checksrc16(String... args) {
194         printargs("checksrc16", args);
195         int asize = args.length;
196         String[] newargs = new String[asize + 1];
197         System.arraycopy(args, 0, newargs, 0, asize);
198         newargs[asize] = "Base.java";
199         pass(newargs);
200         newargs[asize] = "New17.java";
201         fail(newargs);
202     }
203 
checksrc17(String... args)204     protected void checksrc17(String... args) {
205         printargs("checksrc17", args);
206         int asize = args.length;
207         String[] newargs = new String[asize+1];
208         System.arraycopy(args, 0, newargs,0 , asize);
209         newargs[asize] = "New17.java";
210         pass(newargs);
211         newargs[asize] = "New18.java";
212         fail(newargs);
213     }
214 
checksrc18(String... args)215     protected void checksrc18(String... args) {
216         printargs("checksrc18", args);
217         int asize = args.length;
218         String[] newargs = new String[asize+1];
219         System.arraycopy(args, 0, newargs,0 , asize);
220         newargs[asize] = "New17.java";
221         pass(newargs);
222         newargs[asize] = "New18.java";
223         pass(newargs);
224         newargs[asize] = "New110.java";
225         fail(newargs);
226     }
227 
checksrc19(String... args)228     protected void checksrc19(String... args) {
229         printargs("checksrc19", args);
230         checksrc18(args);
231     }
232 
checksrc110(String... args)233     protected void checksrc110(String... args) {
234         printargs("checksrc110", args);
235         int asize = args.length;
236         String[] newargs = new String[asize+1];
237         System.arraycopy(args, 0, newargs,0 , asize);
238         newargs[asize] = "New17.java";
239         pass(newargs);
240         newargs[asize] = "New18.java";
241         pass(newargs);
242         newargs[asize] = "New110.java";
243         pass(newargs);
244     }
245 
checksrc111(String... args)246     protected void checksrc111(String... args) {
247         printargs("checksrc111", args);
248         checksrc110(args);
249     }
250 
pass(String... args)251     protected void pass(String... args) {
252         printargs("pass", args);
253 
254         List<String> jcargs = new ArrayList<String>();
255         jcargs.add("-Xlint:-options");
256 
257         // add in args conforming to List requrements of JavaCompiler
258         for (String onearg : args) {
259             String[] fields = onearg.split(" ");
260             for (String onefield : fields) {
261                 jcargs.add(onefield);
262             }
263         }
264 
265         // empty list is error
266         if (jcargs.isEmpty()) {
267             System.err.println("error: test error in pass() - No arguments");
268             System.err.println("\t arguments:\t" + jcargs);
269             failedCases++;
270             return;
271         }
272 
273         // the last argument is the filename *.java
274         String filename = jcargs.get(jcargs.size() - 1);
275         jcargs.remove(jcargs.size() - 1);
276 
277         boolean creturn = compile(filename, jcargs);
278         // expect a compilation failure, failure if otherwise
279         if (!creturn) {
280             System.err.println("pass: Compilation erroneously failed");
281             System.err.println("\t arguments:\t" + jcargs);
282             System.err.println("\t file     :\t" + filename);
283             failedCases++;
284 
285         }
286 
287     }
288 
fail(String... args)289     protected void fail(String... args) {
290         printargs("fail", args);
291 
292         List<String> jcargs = new ArrayList<String>();
293         jcargs.add("-Xlint:-options");
294 
295         // add in args conforming to List requrements of JavaCompiler
296         for (String onearg : args) {
297             String[] fields = onearg.split(" ");
298             for (String onefield : fields) {
299                 jcargs.add(onefield);
300             }
301         }
302 
303         // empty list is error
304         if (jcargs.isEmpty()) {
305             System.err.println("error: test error in fail()- No arguments");
306             System.err.println("\t arguments:\t" + jcargs);
307             failedCases++;
308             return;
309         }
310 
311         // the last argument is the filename *.java
312         String filename = jcargs.get(jcargs.size() - 1);
313         jcargs.remove(jcargs.size() - 1);
314 
315         boolean creturn = compile(filename, jcargs);
316         // expect a compilation failure, failure if otherwise
317         if (creturn) {
318             System.err.println("fail: Compilation erroneously succeeded");
319             System.err.println("\t arguments:\t" + jcargs);
320             System.err.println("\t file     :\t" + filename);
321             failedCases++;
322         }
323     }
324 
compile(String sourceFile, List<String>options)325     protected boolean compile(String sourceFile, List<String>options) {
326         JavaCompiler.CompilationTask jctask;
327         try (StandardJavaFileManager fm = javacompiler.getStandardFileManager(null, null, null)) {
328             Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(sourceFile);
329 
330             jctask = javacompiler.getTask(
331                 null,    // Writer
332                 fm,      // JavaFileManager
333                 null,    // DiagnosticListener
334                 options, // Iterable<String>
335                 null,    // Iterable<String> classes
336                 files);  // Iterable<? extends JavaFileObject>
337 
338             try {
339                 return jctask.call();
340             } catch (IllegalStateException e) {
341                 System.err.println(e);
342                 return false;
343             }
344         } catch (IOException e) {
345             throw new Error(e);
346         }
347     }
348 
writeSourceFile(String fileName, String body)349     protected void writeSourceFile(String fileName, String body) throws IOException{
350         try (Writer fw = new FileWriter(fileName)) {
351             fw.write(body);
352         }
353     }
354 
genSourceFiles()355     protected void genSourceFiles() throws IOException{
356         /* Create a file that executes with all supported versions. */
357         writeSourceFile("Base.java","public class Base { }\n");
358 
359         /*
360          * Create a file with a new feature in 1.7, not in 1.6 : "<>"
361          */
362         writeSourceFile("New17.java",
363             "import java.util.List;\n" +
364             "import java.util.ArrayList;\n" +
365             "class New17 { List<String> s = new ArrayList<>(); }\n"
366         );
367 
368         /*
369          * Create a file with a new feature in 1.8, not in 1.7 : lambda
370          */
371         writeSourceFile("New18.java",
372             "public class New18 { \n" +
373             "    void m() { \n" +
374             "    new Thread(() -> { }); \n" +
375             "    } \n" +
376             "} \n"
377         );
378 
379         /*
380          * Create a file with a new feature in 1.10, not in 1.9 : var
381          */
382         writeSourceFile("New110.java",
383             "public class New110 { \n" +
384             "    void m() { \n" +
385             "    var tmp = new Thread(() -> { }); \n" +
386             "    } \n" +
387             "} \n"
388         );
389 
390     }
391 
checkClassFileVersion(String filename,String classVersionNumber)392     protected boolean checkClassFileVersion
393         (String filename,String classVersionNumber) {
394         ByteBuffer bb = ByteBuffer.allocate(1024);
395         try (FileChannel fc = new FileInputStream(filename).getChannel()) {
396             bb.clear();
397             if (fc.read(bb) < 0)
398                 throw new IOException("Could not read from file : " + filename);
399             bb.flip();
400             int minor = bb.getShort(4);
401             int major = bb.getShort(6);
402             String fileVersion = major + "." + minor;
403             if (fileVersion.equals(classVersionNumber)) {
404                 return true;
405             } else {
406                 System.err.println("checkClassFileVersion : Failed");
407                 System.err.println("\tclassfile version mismatch");
408                 System.err.println("\texpected : " + classVersionNumber);
409                 System.err.println("\tfound    : " + fileVersion);
410                 return false;
411             }
412         }
413         catch (IOException e) {
414             System.err.println("checkClassFileVersion : Failed");
415             System.err.println("\terror :\t" + e.getMessage());
416             System.err.println("\tfile:\tfilename");
417         }
418         return false;
419     }
420 }
421 
422