test/tools/javac/processing/TestWarnErrorCount.java

Fri, 21 Dec 2012 08:45:43 -0800

author
darcy
date
Fri, 21 Dec 2012 08:45:43 -0800
changeset 1466
b52a38d4536c
parent 1305
9d47f4850714
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8005282: Use @library tag with non-relative path for javac tests
Reviewed-by: jjg

jjg@898 1 /*
jjh@1305 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
jjg@898 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@898 4 *
jjg@898 5 * This code is free software; you can redistribute it and/or modify it
jjg@898 6 * under the terms of the GNU General Public License version 2 only, as
jjg@898 7 * published by the Free Software Foundation.
jjg@898 8 *
jjg@898 9 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@898 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@898 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@898 12 * version 2 for more details (a copy is included in the LICENSE file that
jjg@898 13 * accompanied this code).
jjg@898 14 *
jjg@898 15 * You should have received a copy of the GNU General Public License version
jjg@898 16 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@898 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@898 18 *
jjg@898 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jjg@898 20 * or visit www.oracle.com if you need additional information or have any
jjg@898 21 * questions.
jjg@898 22 */
jjg@898 23
jjg@898 24
jjg@898 25 /*
jjg@898 26 * @test
jjg@898 27 * @bug 7022337
jjg@898 28 * @summary repeated warnings about bootclasspath not set
darcy@1466 29 * @library /tools/javac/lib
jjg@898 30 * @build JavacTestingAbstractProcessor TestWarnErrorCount
jjg@898 31 * @run main TestWarnErrorCount
jjg@898 32 */
jjg@898 33
jjg@898 34 import java.io.*;
jjg@898 35 import java.util.*;
jjg@898 36 import javax.annotation.processing.*;
jjg@898 37 import javax.lang.model.element.*;
jjg@898 38 import javax.tools.*;
jjg@898 39
jjg@898 40 @SupportedOptions({"errKind", "msgrWarnKind", "javaWarnKind"})
jjg@898 41 public class TestWarnErrorCount extends JavacTestingAbstractProcessor {
jjg@898 42 public static void main(String... args) throws Exception {
jjg@898 43 new TestWarnErrorCount().run(args);
jjg@898 44 }
jjg@898 45
jjg@898 46 final int MAX_GEN = 10;
jjg@898 47 final int ERROR_ROUND = MAX_GEN / 2; // when to generate error
jjg@898 48
jjg@898 49 /**
jjg@898 50 * Type of errors to generate in test case.
jjg@898 51 */
jjg@898 52 enum ErrorKind {
jjg@898 53 /** No errors. */
jjg@898 54 NONE,
jjg@898 55 /** Source code errors. */
jjg@898 56 JAVA,
jjg@898 57 /** Errors reported to Messager. */
jjg@898 58 MESSAGER,
jjg@898 59 /** Error as a result of using -Werror. */
jjg@898 60 WERROR,
jjg@898 61 }
jjg@898 62
jjg@898 63 /**
jjg@898 64 * Frequency of warnings in test case.
jjg@898 65 */
jjg@898 66 enum WarnKind {
jjg@898 67 /** No warnings. */
jjg@898 68 NONE {
jjg@898 69 boolean warn(int round) { return false; }
jjg@898 70 int count(int start, int end) { return 0; }
jjg@898 71 },
jjg@898 72 /** Generate a warning if round count is a multiple of 2. */
jjg@898 73 EVERY_TWO {
jjg@898 74 boolean warn(int round) { return (round % 2) == 0; }
jjg@898 75 int count(int start, int end) { return (end / 2) - ((start - 1)/ 2); }
jjg@898 76 },
jjg@898 77 /** Generate a warning if round count is a multiple of 3. */
jjg@898 78 EVERY_THREE {
jjg@898 79 boolean warn(int round) { return (round % 3) == 0; }
jjg@898 80 int count(int start, int end) { return (end / 3) - ((start - 1)/ 3); }
jjg@898 81 },
jjg@898 82 /** Generate a warning every round. */
jjg@898 83 ALL {
jjg@898 84 boolean warn(int round) { return true; }
jjg@898 85 int count(int start, int end) { return (end - start + 1); }
jjg@898 86 };
jjg@898 87
jjg@898 88 /** whether to generate a warning in round 'round'. */
jjg@898 89 abstract boolean warn(int round);
jjg@898 90
jjg@898 91 /** number of warnings generated in a range of rounds, inclusive. */
jjg@898 92 abstract int count(int start, int end);
jjg@898 93 }
jjg@898 94
jjg@898 95
jjg@898 96 /**
jjg@898 97 * Run test.
jjg@898 98 * @param args provide ability to specify particular test cases for debugging.
jjg@898 99 */
jjg@898 100 void run(String... args) throws Exception {
jjg@898 101 for (String arg: args) {
jjg@898 102 if (arg.matches("[0-9]+")) {
jjg@898 103 if (testCases == null)
jjg@898 104 testCases = new HashSet<Integer>();
jjg@898 105 testCases.add(Integer.valueOf(arg));
jjg@898 106 } else if (arg.equals("-stopOnError")) {
jjg@898 107 stopOnError = true;
jjg@898 108 } else
jjg@898 109 throw new IllegalArgumentException(arg);
jjg@898 110 }
jjg@898 111
jjg@898 112 run ();
jjg@898 113
jjg@898 114 if (errors > 0)
jjg@898 115 throw new Exception(errors + " errors found");
jjg@898 116 }
jjg@898 117
jjg@898 118 /**
jjg@898 119 * Run test.
jjg@898 120 */
jjg@898 121 void run() throws Exception {
jjg@898 122 for (ErrorKind ek: ErrorKind.values()) {
jjg@898 123 for (WarnKind mwk: WarnKind.values()) {
jjg@898 124 for (WarnKind jwk: WarnKind.values()) {
jjg@898 125 test(ek, mwk, jwk);
jjg@898 126 if (stopOnError && errors > 0)
jjg@898 127 throw new Exception(errors + " errors found");
jjg@898 128 }
jjg@898 129 }
jjg@898 130 }
jjg@898 131 }
jjg@898 132
jjg@898 133 boolean stopOnError;
jjg@898 134 Set<Integer> testCases;
jjg@898 135 int testNum = 0;
jjg@898 136
jjg@898 137 /**
jjg@898 138 * Run a test case.
jjg@898 139 * @param ek The type of errors to generate
jjg@898 140 * @param mwk The frequency of Messager warnings to generate
jjg@898 141 * @param jwk The frequency of Java warnings to generate
jjg@898 142 */
jjg@898 143 void test(ErrorKind ek, WarnKind mwk, WarnKind jwk) {
jjg@898 144 testNum++;
jjg@898 145
jjg@898 146 if (testCases != null && !testCases.contains(testNum))
jjg@898 147 return;
jjg@898 148
jjg@898 149 System.err.println("Test " + testNum + ": ek:" + ek + " mwk:" + mwk + " jwk:" + jwk);
jjg@898 150
jjg@898 151 File testDir = new File("test" + testNum);
jjg@898 152 testDir.mkdirs();
jjg@898 153
jjg@898 154 String myName = TestWarnErrorCount.class.getSimpleName();
jjg@898 155 File testSrc = new File(System.getProperty("test.src"));
jjg@898 156 File file = new File(testSrc, myName + ".java");
jjg@898 157
jjg@898 158 List<String> args = new ArrayList<String>();
jjg@898 159 args.addAll(Arrays.asList(
jjg@898 160 "-XDrawDiagnostics",
jjg@898 161 "-d", testDir.getPath(),
jjg@898 162 "-processor", myName,
jjg@898 163 // "-XprintRounds",
mcimadamore@908 164 "-Xlint:all,-path",
jjg@898 165 "-AerrKind=" + ek,
jjg@898 166 "-AmsgrWarnKind=" + mwk,
jjg@898 167 "-AjavaWarnKind=" + jwk));
jjg@898 168 if (ek == ErrorKind.WERROR)
jjg@898 169 args.add("-Werror");
jjg@898 170 args.add(file.getPath());
jjg@898 171
jjg@898 172 String out = compile(args.toArray(new String[args.size()]));
jjg@898 173
jjg@898 174 int errsFound = 0;
jjg@898 175 int errsReported = 0;
jjg@898 176 int warnsFound = 0;
jjg@898 177 int warnsReported = 0;
jjg@898 178
jjg@898 179 // Scan the output looking for messages of interest.
jjg@898 180
jjg@898 181 for (String line: out.split("[\r\n]+")) {
jjg@898 182 if (line.contains("compiler.err.")) {
jjg@898 183 errsFound++;
jjg@898 184 } else if (line.contains("compiler.warn.")) {
jjg@898 185 warnsFound++;
jjg@898 186 } else if (line.matches("[0-9]+ error(?:s?)")) {
jjg@898 187 errsReported = Integer.valueOf(line.substring(0, line.indexOf("error")).trim());
jjg@898 188 } else if (line.matches("[0-9]+ warning(?:s?)")) {
jjg@898 189 warnsReported = Integer.valueOf(line.substring(0, line.indexOf("warning")).trim());
jjg@898 190 }
jjg@898 191 }
jjg@898 192
jjg@898 193 // Compute the expected number of errors and warnings, based on
jjg@898 194 // the test case parameters.
jjg@898 195 // This is highly specific to the annotation processor below, and to
jjg@898 196 // the files it generates.
jjg@898 197 // Generally, the rules are:
jjg@898 198 // -- errors stop annotation processing, allowing for one extra "last round"
jjg@898 199 // -- messager warnings are immediate
jjg@898 200 // -- javac warnings are not shown before the final compilation
jjg@898 201 // (FIXME? -Werror does not stop processing for java warnings)
jjg@898 202 int errsExpected;
jjg@898 203 int msgrWarnsExpected;
jjg@898 204 int javaWarnsExpected;
jjg@898 205 switch (ek) {
jjg@898 206 case NONE:
jjg@898 207 errsExpected = 0;
jjg@898 208 msgrWarnsExpected = mwk.count(1, 1 + MAX_GEN + 1);
jjg@898 209 javaWarnsExpected = jwk.count(2, 1 + MAX_GEN);
jjg@898 210 break;
jjg@898 211 case MESSAGER:
jjg@898 212 errsExpected = 1;
jjg@898 213 msgrWarnsExpected = mwk.count(1, ERROR_ROUND + 1);
jjg@898 214 javaWarnsExpected = 0;
jjg@898 215 break;
jjg@898 216 case JAVA:
jjg@898 217 errsExpected = 2;
jjg@898 218 msgrWarnsExpected = mwk.count(1, ERROR_ROUND + 1);
jjg@898 219 javaWarnsExpected = 0;
jjg@898 220 break;
jjg@898 221 case WERROR:
jjg@898 222 errsExpected = (mwk != WarnKind.NONE || jwk != WarnKind.NONE) ? 1 : 0;
jjg@898 223 switch (mwk) {
jjg@898 224 case NONE:
jjg@898 225 msgrWarnsExpected = 0;
jjg@898 226 javaWarnsExpected = (jwk == WarnKind.NONE)
jjg@898 227 ? 0
jjg@898 228 : 1; // this is surprising: javac only reports warning in first file
jjg@898 229 break;
jjg@898 230 case EVERY_TWO:
jjg@898 231 msgrWarnsExpected = mwk.count(1, 2 + 1);
jjg@898 232 javaWarnsExpected = 0;
jjg@898 233 break;
jjg@898 234 case EVERY_THREE:
jjg@898 235 msgrWarnsExpected = mwk.count(1, 3 + 1);
jjg@898 236 javaWarnsExpected = 0;
jjg@898 237 break;
jjg@898 238 case ALL:
jjg@898 239 msgrWarnsExpected = mwk.count(1, 1 + 1);
jjg@898 240 javaWarnsExpected = 0;
jjg@898 241 break;
jjg@898 242 default:
jjg@898 243 throw new IllegalStateException();
jjg@898 244 }
jjg@898 245 break;
jjg@898 246 default:
jjg@898 247 throw new IllegalStateException();
jjg@898 248 }
jjg@898 249
jjg@898 250 int warnsExpected = msgrWarnsExpected + javaWarnsExpected;
jjg@898 251 System.err.println("mwk: " + msgrWarnsExpected
jjg@898 252 + ", jwk: " + javaWarnsExpected
jjg@898 253 + ", total: " + warnsExpected);
jjg@898 254
jjg@898 255 boolean ok;
jjg@898 256 ok = checkEqual("errors", "reported", errsFound, errsReported);
jjg@898 257 ok &= checkEqual("errors", "expected", errsFound, errsExpected);
jjg@898 258 ok &= checkEqual("warnings", "reported", warnsFound, warnsReported);
jjg@898 259 ok &= checkEqual("warnings", "expected", warnsFound, warnsExpected);
jjg@898 260 if (ok)
jjg@898 261 System.err.println("OK");
jjg@898 262
jjg@898 263 System.err.println();
jjg@898 264 }
jjg@898 265
jjg@898 266 String compile(String... args) {
jjg@898 267 StringWriter sw = new StringWriter();
jjg@898 268 PrintWriter pw = new PrintWriter(sw);
jjg@898 269 int rc = com.sun.tools.javac.Main.compile(args, pw);
jjg@898 270 pw.close();
jjg@898 271 String out = sw.toString();
jjg@898 272 if (!out.isEmpty())
jjg@898 273 System.err.println(out);
jjg@898 274 if (rc != 0)
jjg@898 275 System.err.println("compilation failed: rc=" + rc);
jjg@898 276 return out;
jjg@898 277 }
jjg@898 278
jjg@898 279 boolean checkEqual(String l1, String l2, int i1, int i2) {
jjg@898 280 if (i1 != i2)
jjg@898 281 error("number of " + l1 + " found, " + i1 + ", does not match number " + l2 + ", " + i2);
jjg@898 282 return (i1 == i2);
jjg@898 283 }
jjg@898 284
jjg@898 285 void error(String msg) {
jjg@898 286 System.err.println("Error: " + msg);
jjg@898 287 errors++;
jjg@898 288 }
jjg@898 289
jjg@898 290 int errors = 0;
jjg@898 291
jjg@898 292 // ----- Annotation processor -----
jjg@898 293
jjg@898 294 int round = 0;
jjg@898 295
jjg@898 296 @Override
jjg@898 297 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
jjg@898 298 round++;
jjg@898 299
jjg@898 300 ErrorKind ek = ErrorKind.valueOf(options.get("errKind"));
jjg@898 301 WarnKind mwk = WarnKind.valueOf(options.get("msgrWarnKind"));
jjg@898 302 WarnKind jwk = WarnKind.valueOf(options.get("javaWarnKind"));
jjg@898 303 messager.printMessage(Diagnostic.Kind.NOTE,
jjg@898 304 "Round " + round
jjg@898 305 + " " + roundEnv.getRootElements()
jjg@898 306 + ", last round: " + roundEnv.processingOver());
jjg@898 307 messager.printMessage(Diagnostic.Kind.NOTE,
jjg@898 308 "ek: " + ek + ", mwk: " + mwk + ", jwk: " + jwk);
jjg@898 309
jjg@898 310 if (round <= MAX_GEN && !roundEnv.processingOver())
jjg@898 311 generate("Gen" + round,
jjg@898 312 (ek == ErrorKind.JAVA) && (round == ERROR_ROUND),
jjg@898 313 jwk.warn(round));
jjg@898 314
jjg@898 315 if (mwk.warn(round))
jjg@898 316 messager.printMessage(Diagnostic.Kind.WARNING, "round " + round);
jjg@898 317
jjg@898 318 if ((ek == ErrorKind.MESSAGER) && (round == ERROR_ROUND))
jjg@898 319 messager.printMessage(Diagnostic.Kind.ERROR, "round " + round);
jjg@898 320
jjg@898 321 return true;
jjg@898 322 }
jjg@898 323
jjg@898 324 void generate(String name, boolean error, boolean warn) {
jjg@898 325 try {
jjg@898 326 JavaFileObject fo = filer.createSourceFile(name);
jjg@898 327 Writer out = fo.openWriter();
jjg@898 328 try {
jjg@898 329 out.write("class " + name + " {\n"
mcimadamore@1237 330 + (warn ? " void m() throws Exception { try (AutoCloseable ac = null) { } }" : "")
jjg@898 331 + (error ? " ERROR\n" : "")
jjg@898 332 + "}\n");
jjg@898 333 } finally {
jjg@898 334 out.close();
jjg@898 335 }
jjg@898 336 } catch (IOException e) {
jjg@898 337 throw new Error(e);
jjg@898 338 }
jjg@898 339 }
jjg@898 340 }

mercurial