--- /dev/null 2013-06-20 06:41:59.724750638 -0400 +++ new/test/tools/javac/limits/NumArgsTest.java 2013-06-20 12:18:14.342133905 -0400 @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.util.*; +import java.io.*; +import javax.tools.JavaFileObject; + +// More general parameter limit testing framework, and designed so +// that it could be expanded into a general limits-testing framework +// in the future. +public class NumArgsTest { + + private int errors = 0; + private final boolean isStaticMethod; + private final int threshold; + private final String result; + private final String testName; + private final String methodName; + private final NestingDef[] nesting; + private final File testdir; + private static Main compiler = new Main("javac"); + + public NumArgsTest(final int threshold, + final boolean isStaticMethod, + final String result, + final String methodName, + final String testName, + final NestingDef[] nesting) { + this.threshold = threshold; + this.isStaticMethod = isStaticMethod; + this.result = result; + this.methodName = methodName; + this.testName = testName; + this.nesting = nesting; + testdir = new File(testName); + testdir.mkdir(); + } + + public NumArgsTest(final int threshold, + final String result, + final String methodName, + final String testName, + final NestingDef[] nesting) { + this(threshold, false, result, methodName, testName, nesting); + } + + public NumArgsTest(final int threshold, + final String testName, + final NestingDef[] nesting) { + this(threshold, null, null, testName, nesting); + } + + public NumArgsTest(final int threshold, + final String testName, + final String constructorName, + final NestingDef[] nesting) { + this(threshold, null, constructorName, testName, nesting); + } + + protected void writeArgs(final int num, final PrintWriter stream) + throws IOException { + stream.print("int x1"); + for(int i = 1; i < num; i++) + stream.print(", int x" + (i + 1)); + } + + protected void writeMethod(final int num, + final String name, + final PrintWriter stream) + throws IOException { + stream.write("public "); + if (isStaticMethod) stream.write("static "); + if (result == null) + stream.write(""); + else { + stream.write(result); + stream.write(" "); + } + stream.write(name); + stream.write("("); + writeArgs(num, stream); + stream.write(") {}\n"); + } + + protected void writeJavaFile(final int num, + final boolean pass, + final PrintWriter stream) + throws IOException { + final String fullName = testName + (pass ? "Pass" : "Fail"); + stream.write("public class "); + stream.write(fullName); + stream.write(" {\n"); + for(int i = 0; i < nesting.length; i++) + nesting[i].writeBefore(stream); + if (null == methodName) + writeMethod(num, fullName, stream); + else + writeMethod(num, methodName, stream); + for(int i = nesting.length - 1; i >= 0; i--) + nesting[i].writeAfter(stream); + stream.write("}\n"); + } + + public void runTest() throws Exception { + // Run the pass test + final String passTestName = testName + "Pass.java"; + final StringWriter passBody = new StringWriter(); + final PrintWriter passStream = new PrintWriter(passBody); + final File passFile = new File(testdir, passTestName); + final FileWriter passWriter = new FileWriter(passFile); + + writeJavaFile(threshold, true, passStream); + passStream.close(); + passWriter.write(passBody.toString()); + passWriter.close(); + + final StringWriter passSW = new StringWriter(); + final PrintWriter passPW = new PrintWriter(passSW); + final Main passCompiler = new Main("javac", passPW); + final Context passContext = new Context(); + final Log passLog = Log.instance(passContext); + final TestDiagnosticHandler passDiag = + new TestDiagnosticHandler(passLog, "limit.parameters"); + final String[] passArgs = { passFile.toString() }; + final Main.Result passResult = + passCompiler.compile(passArgs, null, passContext, + List.nil(), null, passLog); + + passPW.close(); + + if(passResult.exitCode != 0) { + errors++; + System.err.println("Compilation unexpectedly failed. Body:\n" + + passBody); + System.err.println("Output:\n" + passSW.toString()); + } + + // Run the fail test + final String failTestName = testName + "Fail.java"; + final StringWriter failBody = new StringWriter(); + final PrintWriter failStream = new PrintWriter(failBody); + final File failFile = new File(testdir, failTestName); + final FileWriter failWriter = new FileWriter(failFile); + + writeJavaFile(threshold + 1, false, failStream); + failStream.close(); + failWriter.write(failBody.toString()); + failWriter.close(); + + final StringWriter failSW = new StringWriter(); + final PrintWriter failPW = new PrintWriter(failSW); + final Main failCompiler = new Main("javac", failPW); + final Context failContext = new Context(); + final Log failLog = Log.instance(failContext); + final TestDiagnosticHandler failDiag = + new TestDiagnosticHandler(failLog, "compiler.err.limit.parameters"); + final String[] failArgs = { failFile.toString() }; + final Main.Result failResult = + failCompiler.compile(failArgs, null, failContext, + List.nil(), null, failLog); + + failPW.close(); + + if(failResult.exitCode == 0) { + errors++; + System.err.println("Compilation unexpectedly succeeded."); + System.err.println("Input:\n" + failBody); + } + + if (!failDiag.sawError) { + errors++; + System.err.println("Did not see expected compile error."); + } + + if (errors != 0) + throw new RuntimeException("Test failed with " + + errors + " errors"); + } + + public static NestingDef classNesting(final String name) { + return new NestedClassBuilder(name, false); + } + + public static NestingDef classNesting(final String name, + final boolean isStatic) { + return new NestedClassBuilder(name, isStatic); + } + + protected interface NestingDef { + public abstract void writeBefore(final PrintWriter stream); + public abstract void writeAfter(final PrintWriter stream); + } + + private static class NestedClassBuilder implements NestingDef { + private final String name; + private final boolean isStatic; + public NestedClassBuilder(final String name, final boolean isStatic) { + this.name = name; + this.isStatic = isStatic; + } + public void writeBefore(final PrintWriter stream) { + stream.write("public "); + if (isStatic) stream.write("static"); + stream.write(" class "); + stream.write(name); + stream.write(" {\n"); + } + public void writeAfter(final PrintWriter stream) { + stream.write("}\n"); + } + } + + public class TestDiagnosticHandler extends Log.DiagnosticHandler { + public boolean sawError; + public final String target; + + public TestDiagnosticHandler(final Log log, final String target) { + install(log); + this.target = target; + } + + public void report(final JCDiagnostic diag) { + if (diag.getCode().equals(target)) + sawError = true; + prev.report(diag); + } + } + +}