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