aoqi@0: /* aoqi@0: * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * @test aoqi@0: * @bug 6863465 aoqi@0: * @summary javac doesn't detect circular subclass dependencies via qualified names aoqi@0: * @run main TestCircularClassfile aoqi@0: */ aoqi@0: aoqi@0: import java.io.*; aoqi@0: import java.net.URI; aoqi@0: import java.util.Arrays; aoqi@0: import javax.tools.Diagnostic; aoqi@0: import javax.tools.DiagnosticListener; aoqi@0: import javax.tools.JavaCompiler; aoqi@0: import javax.tools.JavaFileObject; aoqi@0: import javax.tools.SimpleJavaFileObject; aoqi@0: import javax.tools.ToolProvider; aoqi@0: aoqi@0: import com.sun.source.util.JavacTask; aoqi@0: import java.util.EnumSet; aoqi@0: aoqi@0: public class TestCircularClassfile { aoqi@0: aoqi@0: enum ClassName { aoqi@0: A("A"), aoqi@0: B("B"), aoqi@0: C("C"), aoqi@0: OBJECT("Object"); aoqi@0: aoqi@0: String name; aoqi@0: aoqi@0: ClassName(String name) { aoqi@0: this.name = name; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class JavaSource extends SimpleJavaFileObject { aoqi@0: aoqi@0: final static String sourceStub = "class #C extends #S {}"; aoqi@0: aoqi@0: String source; aoqi@0: aoqi@0: public JavaSource(ClassName clazz, ClassName sup) { aoqi@0: super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); aoqi@0: source = sourceStub.replace("#C", clazz.name).replace("#S", sup.name); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public CharSequence getCharContent(boolean ignoreEncodingErrors) { aoqi@0: return source; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public static void main(String... args) throws Exception { aoqi@0: int count = 0; aoqi@0: for (ClassName clazz : EnumSet.of(ClassName.A, ClassName.B, ClassName.C)) { aoqi@0: for (ClassName sup : EnumSet.of(ClassName.A, ClassName.B, ClassName.C)) { aoqi@0: if (sup.ordinal() < clazz.ordinal()) continue; aoqi@0: check("sub_"+count++, clazz, sup); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static JavaSource[] initialSources = new JavaSource[] { aoqi@0: new JavaSource(ClassName.A, ClassName.OBJECT), aoqi@0: new JavaSource(ClassName.B, ClassName.A), aoqi@0: new JavaSource(ClassName.C, ClassName.B) aoqi@0: }; aoqi@0: aoqi@0: static String workDir = System.getProperty("user.dir"); aoqi@0: aoqi@0: static void check(String destPath, ClassName clazz, ClassName sup) throws Exception { aoqi@0: File destDir = new File(workDir, destPath); destDir.mkdir(); aoqi@0: final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); aoqi@0: JavacTask ct = (JavacTask)tool.getTask(null, null, null, aoqi@0: Arrays.asList("-d", destPath), null, Arrays.asList(initialSources)); aoqi@0: ct.generate(); aoqi@0: File fileToRemove = new File(destPath, clazz.name + ".class"); aoqi@0: fileToRemove.delete(); aoqi@0: JavaSource newSource = new JavaSource(clazz, sup); aoqi@0: DiagnosticChecker checker = new DiagnosticChecker(); aoqi@0: ct = (JavacTask)tool.getTask(null, null, checker, aoqi@0: Arrays.asList("-cp", destPath), null, Arrays.asList(newSource)); aoqi@0: ct.analyze(); aoqi@0: if (!checker.errorFound) { aoqi@0: throw new AssertionError(newSource.source); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class DiagnosticChecker implements DiagnosticListener { aoqi@0: aoqi@0: boolean errorFound = false; aoqi@0: aoqi@0: public void report(Diagnostic diagnostic) { aoqi@0: if (diagnostic.getKind() == Diagnostic.Kind.ERROR && aoqi@0: diagnostic.getCode().equals("compiler.err.cyclic.inheritance")) { aoqi@0: errorFound = true; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: }