diff -r 13354e1abba7 -r 3640b60bd0f6 test/tools/javac/diags/RunExamples.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/RunExamples.java Thu Jul 22 11:02:54 2010 -0700 @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2010, 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. + */ + +/** + * @test + * @bug 6968063 + * @summary provide examples of code that generate diagnostics + * @build Example HTMLWriter RunExamples + * @run main RunExamples + */ + +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility to run selected or all examples, writing results to + * stdout, a plain text file or an HTML file. This program can be + * run standalone, or as a jtreg test. + * + * Options: + * -examples dir directory of examples. Defaults to ${test.src}/examples + * -raw run examples with -XDrawDiagnostics + * -showFiles include text of source files in the output + * -verbose verbose output + * -o file write output to file: format will be HTML if + * file has .html extension; otherwise it will be plain text. + * default is to stdout + * -title string specify a title, only applies to HTML output + */ +public class RunExamples { + public static void main(String... args) throws Exception { + boolean jtreg = (System.getProperty("test.src") != null); + File tmpDir; + if (jtreg) { + // use standard jtreg scratch directory: the current directory + tmpDir = new File(System.getProperty("user.dir")); + } else { + tmpDir = new File(System.getProperty("java.io.tmpdir"), + RunExamples.class.getName() + + (new SimpleDateFormat("yyMMddHHmmss")).format(new Date())); + } + Example.setTempDir(tmpDir); + + RunExamples r = new RunExamples(); + + try { + if (r.run(args)) + return; + } finally { + /* VERY IMPORTANT NOTE. In jtreg mode, tmpDir is set to the + * jtreg scratch directory, which is the current directory. + * In case someone is faking jtreg mode, make sure to only + * clean tmpDir when it is reasonable to do so. + */ + if (tmpDir.isDirectory() && + tmpDir.getName().startsWith(RunExamples.class.getName())) { + if (clean(tmpDir)) + tmpDir.delete(); + } + } + + if (jtreg) + throw new Exception(r.errors + " errors occurred"); + else + System.exit(1); + } + + boolean run(String... args) { + Set selectedKeys = new TreeSet(); + Set selectedExamples = new TreeSet(); + File testSrc = new File(System.getProperty("test.src", ".")); + File examplesDir = new File(testSrc, "examples"); + File outFile = null; + boolean raw = false; + boolean showFiles = false; + boolean verbose = false; + String title = null; + + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-k") && (i + 1) < args.length) + selectedKeys.add(args[++i]); + else if (arg.equals("-examples") && (i + 1) < args.length) + examplesDir = new File(args[++i]); + else if (arg.equals("-raw")) + raw = true; + else if (arg.equals("-showFiles")) + showFiles = true; + else if (arg.equals("-verbose")) + verbose = true; + else if (arg.equals("-o") && (i + 1) < args.length) + outFile = new File(args[++i]); + else if (arg.equals("-title") && (i + 1) < args.length) + title = args[++i]; + else if (arg.startsWith("-")) { + error("unknown option: " + arg); + return false; + } else { + while (i < args.length) { + File f = new File(examplesDir, args[i]); + selectedExamples.add(new Example(f)); + i++; + } + } + } + + if (selectedKeys.size() > 0) { + Set examples = getExamples(examplesDir); + nextKey: + for (String k: selectedKeys) { + for (Example e: examples) { + if (e.getDeclaredKeys().contains(k)) + continue nextKey; + } + error("Key " + k + ": no examples found"); + } + } else { + if (selectedExamples.size() == 0) + selectedExamples = getExamples(examplesDir); + } + + try { + Runner r; + if (outFile == null) { + PrintWriter out = new PrintWriter(System.out); + r = new TextRunner(out, showFiles, raw, verbose); + } else if (outFile.getName().endsWith(".html")) + r = new HTMLRunner(outFile, showFiles, raw, verbose, title); + else + r = new TextRunner(outFile, showFiles, raw, verbose); + r.run(selectedExamples); + r.close(); + } catch (IOException e) { + error("Error writing output: " + e); + } + + return (errors == 0); + } + + /** + * Get the complete set of examples to be checked. + */ + Set getExamples(File examplesDir) { + Set results = new TreeSet(); + for (File f: examplesDir.listFiles()) { + if (f.isDirectory() || f.isFile() && f.getName().endsWith(".java")) + results.add(new Example(f)); + } + return results; + } + + /** + * Report an error. + */ + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; + + /** + * Clean the contents of a directory. + */ + static boolean clean(File dir) { + boolean ok = true; + for (File f: dir.listFiles()) { + if (f.isDirectory()) + ok &= clean(f); + ok &= f.delete(); + } + return ok; + } + + static abstract class Runner { + Runner(boolean showFiles, boolean raw, boolean verbose) { + this.showFiles = showFiles; + this.raw = raw; + this.verbose = verbose; + } + + void close() throws IOException { } + + void run(Collection examples) throws IOException { + for (Example e: examples) { + startExample(e); + if (showFiles) { + showFile(e, e.infoFile); + Set srcFiles = new TreeSet(e.srcFiles); + srcFiles.remove(e.infoFile); + showFiles(e, srcFiles); + showFiles(e, e.srcPathFiles); + showFiles(e, e.procFiles); + showFiles(e, e.supportFiles); + } + run(e); + } + } + + void showFiles(Example e, Collection files) throws IOException { + for (File f: files) + showFile(e, f); + } + + abstract void startExample(Example e) throws IOException; + + abstract void showFile(Example e, File f) throws IOException; + + abstract void run(Example e) throws IOException; + + protected String read(File f) throws IOException { + byte[] bytes = new byte[(int) f.length()]; + DataInputStream in = new DataInputStream(new FileInputStream(f)); + try { + in.readFully(bytes); + } finally { + in.close(); + } + return new String(bytes); + } + + protected Pattern copyrightHeaderPat = + Pattern.compile("(?s)(/\\*.*?Copyright.*?\\*/\n)\\s*(.*)"); + protected Pattern infoHeaderPat = + Pattern.compile("(?s)((?://\\s*[a-z]+:[^\n]*\n)+)\\s*(.*)"); + + protected boolean showFiles; + protected boolean raw; + protected boolean verbose; + } + + static class TextRunner extends Runner { + TextRunner(File file, boolean showFiles, boolean raw, boolean verbose) + throws IOException { + super(showFiles, raw, verbose); + this.file = file; + out = new PrintWriter(new FileWriter(file)); + } + + TextRunner(PrintWriter out, boolean showFiles, boolean raw, boolean verbose) + throws IOException { + super(showFiles, raw, verbose); + this.out = out; + } + + @Override + void close() { + if (file != null) + out.close(); + } + + @Override + void startExample(Example e) { + out.println("----- " + e.getName() + " --------------------"); + out.println(); + } + + @Override + void showFile(Example e, File f) { + out.println("--- " + f); + String text; + try { + text = read(f); + } catch (IOException ex) { + text = "Error reading " + f + "; " + ex; + } + Matcher m = copyrightHeaderPat.matcher(text); + if (m.matches()) { + out.println("(Copyright)"); + writeLines(m.group(2)); + } else { + writeLines(text); + } + out.println(); + } + + @Override + void run(Example e) { + // only show Output: header if also showing files + if (showFiles) + out.println("--- Output:"); + e.run(out, raw, verbose); + out.println(); + } + + void writeLines(String text) { + for (String line: text.split("\n")) + out.println(line); + } + + File file; + PrintWriter out; + } + + static class HTMLRunner extends Runner { + HTMLRunner(File file, boolean showFiles, boolean raw, boolean verbose, String title) + throws IOException { + super(showFiles, raw, verbose); + this.file = file; + PrintWriter out = new PrintWriter(new FileWriter(file)); + html = new HTMLWriter(out); + html.startTag(HTMLWriter.HEAD); + if (title != null) { + html.startTag(HTMLWriter.TITLE); + html.write(title); + html.endTag(HTMLWriter.TITLE); + } + html.startTag(HTMLWriter.STYLE); + html.newLine(); + html.writeLine("div.file { background-color:#e0ffe0; margin-left:30px; margin-right:30px;\n" + + " padding: 3px; border: thin solid silver; }"); + html.writeLine("p.file { white-space: pre-wrap; font-family:monospace; margin: 0; }"); + html.writeLine("div.output { background-color:#e0e0ff; margin-left:30px; margin-right:30px;\n" + + " padding: 3px; border: thin solid silver; }"); + html.writeLine("p.output { white-space: pre-wrap; font-family:monospace; margin: 0; }"); + html.writeLine("table.index { border: thin solid silver; }"); + html.writeLine(".copyright { font-size: x-small }"); + html.writeLine(".hidden { display:none }"); + html.writeLine(".unhidden { display:block }"); + html.writeLine(".odd { background-color: #e0e0e0 }"); + html.writeLine(".even { background-color: white }"); + html.endTag(HTMLWriter.STYLE); + html.startTag(HTMLWriter.SCRIPT); + html.writeAttr(HTMLWriter.TYPE, HTMLWriter.TEXT_JAVASCRIPT); + html.writeLine("\nfunction unhide(id) {\n" + + " var item = document.getElementById(id);\n" + + " if (item) {\n" + + " item.className=(item.className=='hidden')?'unhidden':'hidden';\n" + + " }\n" + + "}"); + html.endTag(HTMLWriter.SCRIPT); + html.endTag(HTMLWriter.HEAD); + html.startTag(HTMLWriter.BODY); + if (title != null) { + html.startTag(TITLE_HEADER); + html.write(title); + html.endTag(TITLE_HEADER); + } + } + + @Override + void close() throws IOException { + html.endTag(HTMLWriter.BODY); + html.newLine(); + html.flush(); + } + + @Override + void run(Collection examples) throws IOException { + if (examples.size() > 1) + writeIndex(examples); + super.run(examples); + } + + void writeIndex(Collection examples) throws IOException { + Map> index = new TreeMap>(); + Set initials = new HashSet(); + for (Example e: examples) { + for (String k: e.getDeclaredKeys()) { + Set s = index.get(k); + if (s == null) + index.put(k, s = new TreeSet()); + s.add(e); + } + initials.add(e.getName().substring(0, 1).toUpperCase()); + } + + + if (INDEX_HEADER != null) { + html.startTag(INDEX_HEADER); + html.write("Index"); + html.endTag(INDEX_HEADER); + } + + html.startTag(HTMLWriter.P); + html.writeLine("Examples: "); + for (char initial = 'A'; initial <= 'Z'; initial++) { + String s = String.valueOf(initial); + if (initials.contains(s)) { + html.writeLink("#" + s, s); + } else { + html.write(s); + } + html.newLine(); + } + html.endTag(HTMLWriter.P); + + html.startTag(HTMLWriter.TABLE); + html.writeAttr(HTMLWriter.CLASS, "index"); + html.newLine(); + int row = 0; + for (Map.Entry> entry: index.entrySet()) { + html.startTag(HTMLWriter.TR); + html.writeAttr(HTMLWriter.CLASS, + (row++ % 2 == 0 ? "even" : "odd")); + html.startTag(HTMLWriter.TD); + html.writeAttr("valign", "top"); + html.write(entry.getKey()); + html.endTag(HTMLWriter.TD); + html.newLine(); + html.startTag(HTMLWriter.TD); + html.writeAttr(HTMLWriter.ALIGN, "top"); + String sep = ""; + for (Example e: entry.getValue()) { + html.write(sep); + html.writeLink('#' + e.getName(), e.getName()); + sep = ", "; + } + html.endTag(HTMLWriter.TD); + html.endTag(HTMLWriter.TR); + html.newLine(); + } + html.endTag(HTMLWriter.TABLE); + } + + @Override + void startExample(Example e) throws IOException { + String name = e.getName(); + String initial = name.substring(0, 1).toUpperCase(); + if (!initial.equals(currInitial)) { + html.writeLinkDestination(initial, ""); + currInitial = initial; + } + html.writeLinkDestination(name, ""); + html.startTag(EXAMPLE_HEADER); + html.write(e.getName()); + html.endTag(EXAMPLE_HEADER); + } + + @Override + void showFile(Example e, File f) throws IOException { + String text; + try { + text = read(f); + } catch (IOException ex) { + text = "Error reading " + f + ": " + ex; + } + if (!f.equals(e.file)) { + html.startTag(FILE_HEADER); + html.write(e.file.toURI().relativize(f.toURI()).toString()); + html.endTag(FILE_HEADER); + } + html.startTag(HTMLWriter.DIV); + html.writeAttr(CLASS, FILE); + + String legalHeader; + Matcher m1 = copyrightHeaderPat.matcher(text); + if (m1.matches()) { + legalHeader = m1.group(1); + text = m1.group(2); + } else + legalHeader = null; + + String infoHeader; + Matcher m2 = infoHeaderPat.matcher(text); + if (m2.matches()) { + infoHeader = m2.group(1); + text = m2.group(2); + } else + infoHeader = null; + + String legalId = null, infoId = null; + if (legalHeader != null || infoHeader != null) { + String sep = ""; + html.startTag(HTMLWriter.SPAN); + html.writeStyleAttr("float: right"); + if (legalHeader != null) { + legalId = nextId(); + html.startTag(HTMLWriter.A); + html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + legalId + "');"); + //html.writeEntity("©"); + html.write("Copyright"); + html.endTag(HTMLWriter.A); + sep = ", "; + } + if (infoHeader != null) { + html.write(sep); + infoId = nextId(); + html.startTag(HTMLWriter.A); + html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + infoId + "');"); + html.write("Info"); + html.endTag(HTMLWriter.A); + sep = ", "; + } + html.endTag(HTMLWriter.SPAN); + } + + html.startTag(HTMLWriter.P); + html.writeAttr(CLASS, FILE); + if (legalHeader != null) { + html.startTag(HTMLWriter.SPAN); + html.writeAttr(HTMLWriter.CLASS, "hidden"); + html.writeAttr(HTMLWriter.ID, legalId); + html.write(legalHeader); + html.newLine(); + html.endTag(HTMLWriter.SPAN); + } + if (infoHeader != null) { + html.startTag(HTMLWriter.SPAN); + html.writeAttr(HTMLWriter.CLASS, "hidden"); + html.writeAttr(HTMLWriter.ID, infoId); + html.write(infoHeader); + html.newLine(); + html.endTag(HTMLWriter.SPAN); + } + html.write(text); + html.endTag(HTMLWriter.P); + + html.endTag(HTMLWriter.DIV); + } + + @Override + void run(Example e) throws IOException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.run(pw, raw, verbose); + pw.flush(); + + // only show Output: header if also showing files + if (showFiles) { + html.startTag(OUTPUT_HEADER); + html.write("Output:"); + html.endTag(OUTPUT_HEADER); + } + + html.startTag(HTMLWriter.DIV); + html.writeAttr(CLASS, OUTPUT); + html.startTag(HTMLWriter.P); + html.writeAttr(CLASS, OUTPUT); + String[] lines = sw.toString().split("\n"); + for (String line: lines) { + html.write(line); + html.newLine(); + } + html.endTag(HTMLWriter.P); + html.endTag(HTMLWriter.DIV); + } + + String nextId() { + return "id" + (nextId++); + } + + File file; + HTMLWriter html; + int nextId; + String currInitial = ""; + + static final String TITLE_HEADER = HTMLWriter.H3; + static final String INDEX_HEADER = HTMLWriter.H4; + static final String EXAMPLE_HEADER = HTMLWriter.H4; + static final String FILE_HEADER = HTMLWriter.H5; + static final String OUTPUT_HEADER = HTMLWriter.H5; + static final String CLASS = "class"; + static final String FILE = "file"; + static final String OUTPUT = "output"; + } +} + +