NumArgsTest.java revision 3294:9adfb22ff08f
1/* 2 * Copyright (c) 2013, 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 24import com.sun.tools.javac.api.*; 25import com.sun.tools.javac.file.*; 26import java.io.*; 27import java.util.*; 28import javax.tools.*; 29 30// More general parameter limit testing framework, and designed so 31// that it could be expanded into a general limits-testing framework 32// in the future. 33public class NumArgsTest { 34 35 private static final NumArgsTest.NestingDef[] NO_NESTING = {}; 36 37 // threshold is named as such because "threshold" args is expected 38 // to pass, and "threshold" + 1 args is expected to fail. 39 private final int threshold; 40 private final boolean isStaticMethod; 41 private final String result; 42 private final String testName; 43 private final String methodName; 44 private final NestingDef[] nesting; 45 private final File testdir; 46 private final JavacTool tool = JavacTool.create(); 47 private final JavacFileManager fm = 48 tool.getStandardFileManager(null, null, null); 49 private int errors = 0; 50 51 public NumArgsTest(final int threshold, 52 final boolean isStaticMethod, 53 final String result, 54 final String methodName, 55 final String testName, 56 final NestingDef[] nesting) { 57 this.threshold = threshold; 58 this.isStaticMethod = isStaticMethod; 59 this.result = result; 60 this.methodName = methodName; 61 this.testName = testName; 62 this.nesting = nesting; 63 testdir = new File(testName); 64 testdir.mkdir(); 65 } 66 67 public NumArgsTest(final int threshold, 68 final boolean isStaticMethod, 69 final String result, 70 final String methodName, 71 final String testName) { 72 this(threshold, isStaticMethod, result, methodName, 73 testName, NO_NESTING); 74 } 75 76 public NumArgsTest(final int threshold, 77 final String result, 78 final String methodName, 79 final String testName, 80 final NestingDef[] nesting) { 81 this(threshold, false, result, methodName, testName, nesting); 82 } 83 84 public NumArgsTest(final int threshold, 85 final String result, 86 final String methodName, 87 final String testName) { 88 this(threshold, false, result, methodName, testName, NO_NESTING); 89 } 90 91 public NumArgsTest(final int threshold, 92 final String testName, 93 final NestingDef[] nesting) { 94 this(threshold, null, null, testName, nesting); 95 } 96 97 public NumArgsTest(final int threshold, 98 final String testName) { 99 this(threshold, null, null, testName, NO_NESTING); 100 } 101 102 public NumArgsTest(final int threshold, 103 final String testName, 104 final String constructorName, 105 final NestingDef[] nesting) { 106 this(threshold, null, constructorName, testName, nesting); 107 } 108 109 protected void writeArgs(final int num, final PrintWriter stream) 110 throws IOException { 111 stream.print("int x1"); 112 for(int i = 1; i < num; i++) 113 stream.print(", int x" + (i + 1)); 114 } 115 116 protected void writeMethod(final int num, 117 final String name, 118 final PrintWriter stream) 119 throws IOException { 120 stream.write("public "); 121 if (isStaticMethod) stream.write("static "); 122 if (result == null) 123 stream.write(""); 124 else { 125 stream.write(result); 126 stream.write(" "); 127 } 128 stream.write(name); 129 stream.write("("); 130 writeArgs(num, stream); 131 stream.write(") {}\n"); 132 } 133 134 protected void writeJavaFile(final int num, 135 final boolean pass, 136 final PrintWriter stream) 137 throws IOException { 138 final String fullName = testName + (pass ? "Pass" : "Fail"); 139 stream.write("public class "); 140 stream.write(fullName); 141 stream.write(" {\n"); 142 for(int i = 0; i < nesting.length; i++) 143 nesting[i].writeBefore(stream); 144 if (null == methodName) 145 writeMethod(num, fullName, stream); 146 else 147 writeMethod(num, methodName, stream); 148 for(int i = nesting.length - 1; i >= 0; i--) 149 nesting[i].writeAfter(stream); 150 stream.write("}\n"); 151 } 152 153 public void runTest() throws Exception { 154 // Run the pass test 155 final String passTestName = testName + "Pass.java"; 156 final StringWriter passBody = new StringWriter(); 157 final PrintWriter passStream = new PrintWriter(passBody); 158 final File passFile = new File(testdir, passTestName); 159 final FileWriter passWriter = new FileWriter(passFile); 160 161 writeJavaFile(threshold, true, passStream); 162 passStream.close(); 163 passWriter.write(passBody.toString()); 164 passWriter.close(); 165 166 final StringWriter passSW = new StringWriter(); 167 final String[] passArgs = { passFile.toString() }; 168 final Iterable<? extends JavaFileObject> passFiles = 169 fm.getJavaFileObjectsFromFiles(Arrays.asList(passFile)); 170 final JavaCompiler.CompilationTask passTask = 171 tool.getTask(passSW, fm, null, null, null, passFiles); 172 173 if (!passTask.call()) { 174 errors++; 175 System.err.println("Compilation unexpectedly failed. Body:\n" + 176 passBody); 177 System.err.println("Output:\n" + passSW.toString()); 178 } 179 180 // Run the fail test 181 final String failTestName = testName + "Fail.java"; 182 final StringWriter failBody = new StringWriter(); 183 final PrintWriter failStream = new PrintWriter(failBody); 184 final File failFile = new File(testdir, failTestName); 185 final FileWriter failWriter = new FileWriter(failFile); 186 187 writeJavaFile(threshold + 1, false, failStream); 188 failStream.close(); 189 failWriter.write(failBody.toString()); 190 failWriter.close(); 191 192 final StringWriter failSW = new StringWriter(); 193 final TestDiagnosticHandler failDiag = 194 new TestDiagnosticHandler("compiler.err.limit.parameters"); 195 final Iterable<? extends JavaFileObject> failFiles = 196 fm.getJavaFileObjectsFromFiles(Arrays.asList(failFile)); 197 final JavaCompiler.CompilationTask failTask = 198 tool.getTask(failSW, 199 tool.getStandardFileManager(null, null, null), 200 failDiag, 201 null, 202 null, 203 failFiles); 204 205 if (failTask.call()) { 206 errors++; 207 System.err.println("Compilation unexpectedly succeeded."); 208 System.err.println("Input:\n" + failBody); 209 } 210 211 if (!failDiag.sawError) { 212 errors++; 213 System.err.println("Did not see expected compile error."); 214 } 215 216 if (errors != 0) 217 throw new RuntimeException("Test failed with " + 218 errors + " errors"); 219 } 220 221 public static NestingDef classNesting(final String name) { 222 return new NestedClassBuilder(name, false); 223 } 224 225 public static NestingDef classNesting(final String name, 226 final boolean isStatic) { 227 return new NestedClassBuilder(name, isStatic); 228 } 229 230 protected interface NestingDef { 231 public abstract void writeBefore(final PrintWriter stream); 232 public abstract void writeAfter(final PrintWriter stream); 233 } 234 235 private static class NestedClassBuilder implements NestingDef { 236 private final String name; 237 private final boolean isStatic; 238 public NestedClassBuilder(final String name, final boolean isStatic) { 239 this.name = name; 240 this.isStatic = isStatic; 241 } 242 public void writeBefore(final PrintWriter stream) { 243 stream.write("public "); 244 if (isStatic) stream.write("static"); 245 stream.write(" class "); 246 stream.write(name); 247 stream.write(" {\n"); 248 } 249 public void writeAfter(final PrintWriter stream) { 250 stream.write("}\n"); 251 } 252 } 253 254 public class TestDiagnosticHandler<T> implements DiagnosticListener<T> { 255 public boolean sawError; 256 public final String target; 257 258 public TestDiagnosticHandler(final String target) { 259 this.target = target; 260 } 261 262 public void report(final Diagnostic<? extends T> diag) { 263 if (diag.getCode().equals(target)) 264 sawError = true; 265 } 266 } 267 268} 269