1 /* 2 * Copyright (c) 2010, 2015, 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 6863465 27 * @summary javac doesn't detect circular subclass dependencies via qualified names 28 * @modules jdk.compiler 29 * @run main TestCircularClassfile 30 */ 31 32 import java.io.*; 33 import java.net.URI; 34 import java.util.Arrays; 35 import javax.tools.Diagnostic; 36 import javax.tools.DiagnosticListener; 37 import javax.tools.JavaCompiler; 38 import javax.tools.JavaFileObject; 39 import javax.tools.SimpleJavaFileObject; 40 import javax.tools.ToolProvider; 41 42 import com.sun.source.util.JavacTask; 43 import java.util.EnumSet; 44 45 public class TestCircularClassfile { 46 47 enum ClassName { 48 A("A"), 49 B("B"), 50 C("C"), 51 OBJECT("Object"); 52 53 String name; 54 ClassName(String name)55 ClassName(String name) { 56 this.name = name; 57 } 58 } 59 60 static class JavaSource extends SimpleJavaFileObject { 61 62 final static String sourceStub = "class #C extends #S {}"; 63 64 String source; 65 JavaSource(ClassName clazz, ClassName sup)66 public JavaSource(ClassName clazz, ClassName sup) { 67 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 68 source = sourceStub.replace("#C", clazz.name).replace("#S", sup.name); 69 } 70 71 @Override getCharContent(boolean ignoreEncodingErrors)72 public CharSequence getCharContent(boolean ignoreEncodingErrors) { 73 return source; 74 } 75 } 76 main(String... args)77 public static void main(String... args) throws Exception { 78 int count = 0; 79 for (ClassName clazz : EnumSet.of(ClassName.A, ClassName.B, ClassName.C)) { 80 for (ClassName sup : EnumSet.of(ClassName.A, ClassName.B, ClassName.C)) { 81 if (sup.ordinal() < clazz.ordinal()) continue; 82 check("sub_"+count++, clazz, sup); 83 } 84 } 85 } 86 87 static JavaSource[] initialSources = new JavaSource[] { 88 new JavaSource(ClassName.A, ClassName.OBJECT), 89 new JavaSource(ClassName.B, ClassName.A), 90 new JavaSource(ClassName.C, ClassName.B) 91 }; 92 93 static String workDir = System.getProperty("user.dir"); 94 check(String destPath, ClassName clazz, ClassName sup)95 static void check(String destPath, ClassName clazz, ClassName sup) throws Exception { 96 File destDir = new File(workDir, destPath); destDir.mkdir(); 97 final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 98 JavacTask ct = (JavacTask)tool.getTask(null, null, null, 99 Arrays.asList("-d", destPath), null, Arrays.asList(initialSources)); 100 ct.generate(); 101 File fileToRemove = new File(destPath, clazz.name + ".class"); 102 fileToRemove.delete(); 103 JavaSource newSource = new JavaSource(clazz, sup); 104 DiagnosticChecker checker = new DiagnosticChecker(); 105 ct = (JavacTask)tool.getTask(null, null, checker, 106 Arrays.asList("-cp", destPath), null, Arrays.asList(newSource)); 107 ct.analyze(); 108 if (!checker.errorFound) { 109 throw new AssertionError(newSource.source); 110 } 111 } 112 113 static class DiagnosticChecker implements DiagnosticListener<JavaFileObject> { 114 115 boolean errorFound = false; 116 report(Diagnostic<? extends JavaFileObject> diagnostic)117 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 118 if (diagnostic.getKind() == Diagnostic.Kind.ERROR && 119 diagnostic.getCode().equals("compiler.err.cyclic.inheritance")) { 120 errorFound = true; 121 } 122 } 123 } 124 } 125