Mercurial > hg > release > icedtea6-1.4.1
changeset 1201:76b5306fead0
Upgrade to jtreg-4_0-src-b02-15_oct_2008.
line wrap: on
line diff
--- a/ChangeLog Sun Nov 09 22:27:11 2008 +0100 +++ b/ChangeLog Sun Nov 09 22:29:59 2008 +0100 @@ -1,3 +1,24 @@ +2008-11-09 Mark Wielaard <mark@klomp.org> + + * test/jtreg/README, + test/jtreg/com/sun/javatest/diff/HTMLReporter.java, + test/jtreg/com/sun/javatest/diff/Main.java, + test/jtreg/com/sun/javatest/diff/MultiMap.java, + test/jtreg/com/sun/javatest/diff/ReportReader.java, + test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java, + test/jtreg/com/sun/javatest/diff/i18n.properties, + test/jtreg/com/sun/javatest/regtest/Main.java, + test/jtreg/com/sun/javatest/regtest/MainAction.java, + test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java, + test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java, + test/jtreg/com/sun/javatest/regtest/i18n.properties, + test/jtreg/com/sun/javatest/diff/Diff.java, + test/jtreg/com/sun/javatest/diff/Fault.java, + test/jtreg/com/sun/javatest/diff/HTMLWriter.java, + test/jtreg/com/sun/javatest/diff/StandardDiff.java, + test/jtreg/com/sun/javatest/diff/SuperDiff.java, + Upgrade to jtreg-4_0-src-b02-15_oct_2008. + 2008-11-09 Mark Wielaard <mark@klomp.org> * .hgignore: Add test/check-.*log.
--- a/test/jtreg/README Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/README Sun Nov 09 22:29:59 2008 +0100 @@ -20,7 +20,7 @@ This version is based on: - jtharness-oss-4_1_3a-dev -- jtreg-4_0-src-b01-29_apr_2008 +- jtreg-4_0-src-b02-15_oct_2008 IcedJTReg is distrubuted under the GPLv2.0, like jtreg and jtharness. See the documents in the legal directory included in this release.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jtreg/com/sun/javatest/diff/Diff.java Sun Nov 09 22:29:59 2008 +0100 @@ -0,0 +1,161 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.javatest.diff; + +import com.sun.javatest.Status; +import com.sun.javatest.TestResult; +import com.sun.javatest.TestSuite; +import com.sun.javatest.WorkDirectory; +import com.sun.javatest.util.I18NResourceBundle; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public abstract class Diff { + + public abstract boolean report(File outFile) throws Fault, InterruptedException; + + protected boolean diff(List<File> files, File outFile) + throws Fault, InterruptedException { + this.outFile = outFile; + List<DiffReader> list = new ArrayList<DiffReader>(); + for (File f: files) + list.add(open(f)); + + PrintWriter prevOut = out; + if (out == null && outFile != null) { + try { + out = new PrintWriter(new BufferedWriter(new FileWriter(outFile))); // FIXME don't want to use PrintWriter + } catch (IOException e) { + throw new Fault(i18n, "diff.cantOpenFile", outFile, e); + } + } + + try { + initComparator(); + + initReporter(); + reporter.setTitle(title); + reporter.setComparator(comparator); + reporter.setReaders(list); + + List<int[]> testCounts = new ArrayList<int[]>(); + MultiMap<String,TestResult> table = new MultiMap<String,TestResult>(); + for (DiffReader r: list) { + int index = table.addColumn(r.getFile().getPath()); + int[] counts = new int[Status.NUM_STATES]; + for (TestResult tr: r) { + table.addRow(index, tr.getTestName(), tr); + counts[tr.getStatus().getType()]++; + } + testCounts.add(counts); + } + reporter.setTestCounts(testCounts); + + try { + reporter.write(table); + } catch (IOException e) { + throw new Fault(i18n, "diff.ioError", e); + } + + return (reporter.diffs == 0); + } finally { + if (out != prevOut) { +// try { + out.close(); +// } catch (IOException e) { +// throw new Fault(i18n, "main.ioError", e); +// } + out = prevOut; + } + } + } + + protected void initFormat() { + if (format == null && outFile != null) { + String name = outFile.getName(); + int dot = name.lastIndexOf("."); + if (dot != -1) + format = name.substring(dot + 1).toLowerCase(); + } + } + + protected void initReporter() throws Fault { + if (reporter == null) { + try { + initFormat(); + if (format != null && format.equals("html")) + reporter = new HTMLReporter(out); + else + reporter = new SimpleReporter(out); + } catch (IOException e) { + throw new Fault(i18n, "diff.cantOpenReport", e); + } + } + } + + protected void initComparator() { + if (comparator == null) + comparator = new StatusComparator(includeReason); + } + + protected DiffReader open(File f) throws Fault { + if (!f.exists()) + throw new Fault(i18n, "main.cantFindFile", f); + + try { + if (WorkDirectoryReader.accepts(f)) + return new WorkDirectoryReader(f); + + if (ReportReader.accepts(f)) + return new ReportReader(f); + + throw new Fault(i18n, "main.unrecognizedFile", f); + + } catch (TestSuite.Fault e) { + throw new Fault(i18n, "main.cantOpenFile", f, e); + } catch (WorkDirectory.Fault e) { + throw new Fault(i18n, "main.cantOpenFile", f, e); + } catch (IOException e) { + throw new Fault(i18n, "main.cantOpenFile", f, e); + } + + } + + protected File outFile; + protected PrintWriter out; + protected Comparator<TestResult> comparator; + protected Reporter reporter; + protected boolean includeReason; + protected String format; + protected String title; + private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Diff.class); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jtreg/com/sun/javatest/diff/Fault.java Sun Nov 09 22:29:59 2008 +0100 @@ -0,0 +1,40 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.javatest.diff; + +import com.sun.javatest.util.I18NResourceBundle; + +/** + * Exception to report a problem while executing in Main. + */ +public class Fault extends Exception { + + static final long serialVersionUID = 1607979458544175906L; + + Fault(I18NResourceBundle i18n, String s, Object... args) { + super(i18n.getString(s, args)); + } +}
--- a/test/jtreg/com/sun/javatest/diff/HTMLReporter.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/diff/HTMLReporter.java Sun Nov 09 22:29:59 2008 +0100 @@ -33,7 +33,6 @@ import com.sun.javatest.TestResult; import com.sun.javatest.Status; -import com.sun.javatest.util.HTMLWriter; import com.sun.javatest.util.I18NResourceBundle; import static com.sun.javatest.util.HTMLWriter.*; @@ -47,8 +46,8 @@ * Report differences to an HTML file. */ public class HTMLReporter extends Reporter { - - /** Creates a new instance of SimpleDiffReporter */ + + /** Creates a new instance of HTMLReporter */ public HTMLReporter(Writer out) throws IOException { this.out = new HTMLWriter(out, DOCTYPE); this.out.setI18NResourceBundle(i18n); @@ -56,10 +55,40 @@ public void write(MultiMap<String, TestResult> table) throws IOException { this.table = table; - size = table.getColumns(); - + + startReport(title); + + out.startTag(H1); + if (title == null) + out.writeI18N("html.head.notitle"); + else + out.writeI18N("html.head.title", title); + out.endTag(H1); + + writeIndexTable(); + writeMainTable(); + writeSummary(); + + endReport(); + } + + protected void startReport(String title) throws IOException { out.startTag(HTML); + writeHead(title); + out.startTag(BODY); + } + + protected void endReport() throws IOException { + out.startTag(HR); + out.writeI18N("html.generatedAt", new Date()); + out.endTag(BODY); + + out.endTag(HTML); + out.flush(); + } + + protected void writeHead(String title) throws IOException { out.startTag(HEAD); out.startTag(TITLE); if (title == null) @@ -74,40 +103,24 @@ out.write("tr.head { background-color:#dddddd }"); out.write("tr.odd { background-color:#eeeeee }"); out.write("tr.even { background-color:white } "); - out.write("td { padding: 0 1em }"); + out.write("td { padding: 0 .5em }"); out.write("td.pass { background-color:#ddffdd } "); out.write("td.fail { background-color:#ffdddd } "); out.write("td.error { background-color:#ddddff } "); out.write("td.notRun { background-color:#dddddd } "); + out.write("th { padding: 0 .5em }"); out.write("hr { margin-top:30px; }"); out.write("\n"); out.endTag(STYLE); out.endTag(HEAD); - - out.startTag(BODY); - out.startTag(H1); - if (title == null) - out.writeI18N("html.head.notitle"); - else - out.writeI18N("html.head.title", title); - out.endTag(H1); - writeHead(); - writeBody(); - writeSummary(); - - out.startTag(HR); - out.writeI18N("html.generatedAt", new Date()); - out.endTag(BODY); - - out.endTag(HTML); - out.flush(); + } - - private void writeHead() throws IOException { + + private void writeIndexTable() throws IOException { out.startTag(H2); out.writeI18N("html.head.sets"); out.endTag(H2); - + out.startTag(TABLE); out.writeAttr(FRAME, BOX); out.writeAttr(RULES, GROUPS); @@ -120,6 +133,7 @@ out.startTag(TH); out.writeI18N("html.th.location"); out.endTag(TH); + writeIndexTableInfoHeadings(); // out.startTag(TH); // out.writeI18N("html.th.type"); // out.endTag(TH); @@ -146,16 +160,17 @@ out.endTag(TH); out.endTag(TR); out.endTag(THEAD); - + out.startTag(TBODY); for (int i = 0; i < size; i++) { out.startTag(TR); out.writeAttr(CLASS, (i % 2 == 0 ? EVEN : ODD)); out.startTag(TD); - out.write(String.valueOf(i)); + out.write(String.valueOf(i + 1)); out.endTag(TD); out.startTag(TD); out.write(table.getColumnName(i)); + writeIndexTableInfoValues(table.getColumnName(i)); out.endTag(TD); // out.startTag(TD); // out.write("??"); @@ -166,7 +181,7 @@ out.startTag(TD); if (counts[c] > 0) out.write(String.valueOf(counts[c])); - else + else out.writeEntity(" "); total += counts[c]; out.endTag(TD); @@ -179,8 +194,14 @@ out.endTag(TBODY); out.endTag(TABLE); } - - private void writeBody() throws IOException { + + protected void writeIndexTableInfoHeadings() throws IOException { + } + + protected void writeIndexTableInfoValues(String name) throws IOException { + } + + private void writeMainTable() throws IOException { diffs = 0; for (Map.Entry<String, MultiMap.Entry<TestResult>> e: table.entrySet()) { String testName = e.getKey(); @@ -202,7 +223,10 @@ out.endTag(TH); for (int i = 0; i < result.getSize(); i++) { out.startTag(TH); - out.writeI18N("html.th.setN", i); + if (compact) + out.write(String.valueOf(i + 1)); + else + out.writeI18N("html.th.setN", i + 1); out.endTag(TH); } out.endTag(TR); @@ -222,36 +246,24 @@ if (wd != null) trFile = new File(wd, tr.getWorkRelativePath()); } + out.startTag(TD); Status s = (tr == null ? null : tr.getStatus()); - out.startTag(TD); - String classAttr; - String text; - switch (s == null ? Status.NOT_RUN : s.getType()) { - case Status.PASSED: - classAttr = PASS; - text = i18n.getString("html.pass"); - break; - case Status.FAILED: - classAttr = FAIL; - text = i18n.getString("html.fail"); - break; - case Status.ERROR: - classAttr = ERROR; - text = i18n.getString("html.error"); - break; - default: - classAttr = NOT_RUN; - text = i18n.getString("html.notRun"); - break; - } - out.writeAttr(CLASS, classAttr); + out.writeAttr(CLASS, getClassAttr(s)); + String text = getText(s); if (trFile != null && trFile.exists()) { out.startTag(A); out.writeAttr(HREF, trFile.toURI().toString()); - out.write(text); + if (text.startsWith("&")) + out.writeEntity(text); + else + out.write(text); out.endTag(A); - } else - out.write(text); + } else { + if (text.startsWith("&")) + out.writeEntity(text); + else + out.write(text); + } out.endTag(TD); } out.endTag(TR); @@ -262,7 +274,7 @@ out.endTag(TABLE); } } - + private void writeSummary() throws IOException { out.startTag(P); if (diffs == 0) @@ -271,27 +283,60 @@ out.writeI18N("html.diffs.count", diffs); out.endTag(P); } - + + protected String getClassAttr(Status s) { + switch (s == null ? Status.NOT_RUN : s.getType()) { + case Status.PASSED: + return PASS; + case Status.FAILED: + return FAIL; + case Status.ERROR: + return ERROR; + default: + return NOT_RUN; + } + } + + protected String getText(Status s) { + if (statusStrings == null) { + statusStrings = new String[Status.NUM_STATES]; + if (compact) { + statusStrings[Status.PASSED] = i18n.getString("html.pass.compact"); + statusStrings[Status.FAILED] = i18n.getString("html.fail.compact"); + statusStrings[Status.ERROR] = i18n.getString("html.error.compact"); + statusStrings[Status.NOT_RUN] = i18n.getString("html.notRun.compact"); + } else { + statusStrings[Status.PASSED] = i18n.getString("html.pass"); + statusStrings[Status.FAILED] = i18n.getString("html.fail"); + statusStrings[Status.ERROR] = i18n.getString("html.error"); + statusStrings[Status.NOT_RUN] = i18n.getString("html.notRun"); + } + } + return statusStrings[s == null ? Status.NOT_RUN : s.getType()]; + } + + private String[] statusStrings; + + protected final HTMLWriter out; private MultiMap<String, TestResult> table; private int size; - private HTMLWriter out; - - private static final String DOCTYPE = + + private static final String DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd\">"; - + // HTML tags private static final String THEAD = "thead"; private static final String TBODY = "tbody"; - + // HTML attribute names private static final String CLASS = "class"; private static final String FRAME = "frame"; private static final String RULES = "rules"; - + // HTML attribute values private static final String BOX = "box"; private static final String GROUPS = "groups"; - + // HTML class values private static final String HEAD = "head"; private static final String ODD = "odd"; @@ -300,6 +345,7 @@ private static final String FAIL = "fail"; private static final String ERROR = "error"; private static final String NOT_RUN = "notRun"; - + + private boolean compact = Boolean.TRUE.equals(Boolean.getBoolean("jtdiff.html.compact")); private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(HTMLReporter.class); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jtreg/com/sun/javatest/diff/HTMLWriter.java Sun Nov 09 22:29:59 2008 +0100 @@ -0,0 +1,558 @@ +/* + * Copyright 1996-2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.javatest.diff; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.net.URL; +import com.sun.javatest.util.I18NResourceBundle; + +/** + * A class to facilitate writing HTML via a stream. + */ +public class HTMLWriter +{ + /** + * Create an HTMLWriter object, using a default doctype for HTML 3.2. + * @param out a Writer to which to write the generated HTML + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out) throws IOException { + this(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"); + } + + /** + * Create an HTMLWriter object, using a specifed doctype header. + * @param out a Writer to which to write the generated HTML + * @param docType a string containing a doctype header for the HTML to be generetaed + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, String docType) throws IOException { + if (out instanceof BufferedWriter) + this.out = (BufferedWriter) out; + else + this.out = new BufferedWriter(out); + this.out.write(docType); + this.out.newLine(); + } + + /** + * Create an HTMLWriter object, using a specified bundle for l0calizing messages. + * @param out a Writer to which to write the generated HTML + * @param i18n a resource bundle to use to localize messages + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, I18NResourceBundle i18n) throws IOException { + this(out); + this.i18n = i18n; + } + + + /** + * Create an HTMLWriter object, using a specifed doctype header and + * using a specified bundle for l0calizing messages. + * @param out a Writer to which to write the generated HTML + * @param docType a string containing a doctype header for the HTML to be generetaed + * @param i18n a resource bundle to use to localize messages + * @throws IOException if there is a problem writing to the underlying stream + */ + public HTMLWriter(Writer out, String docType, I18NResourceBundle i18n) throws IOException { + this(out, docType); + this.i18n = i18n; + } + + /** + * Set the reource bundle to be used for localizing messages. + * @param i18n the resource bundle to be used for localizing messages + */ + public void setI18NResourceBundle(I18NResourceBundle i18n) { + this.i18n = i18n; + } + + /** + * Flush the stream, and the underlying output stream. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void flush() throws IOException { + out.flush(); + } + + /** + * Close the stream, and the underlying output stream. + * @throws IOException if there is a problem closing the underlying stream + */ + public void close() throws IOException { + out.close(); + } + + /** + * Write a newline to the underlying output stream. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void newLine() throws IOException { + out.newLine(); + } + + /** + * Start an HTML tag. If a prior tag has been started, it will + * be closed first. Once a tag has been opened, attributes for the + * tag may be written out, followed by body content before finally + * ending the tag. + * @param tag the tag to be started + * @throws IOException if there is a problem writing to the underlying stream + * @see #writeAttr + * @see #write + * @see #endTag + */ + public void startTag(String tag) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + newLine(); + out.write("<"); + out.write(tag); + state = IN_TAG; + } + + /** + * Finish an HTML tag. It is expected that a call to endTag will match + * a corresponding earlier call to startTag, but there is no formal check + * for this. + * @param tag the tag to be closed. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void endTag(String tag) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + out.newLine(); + } + out.write("</"); + out.write(tag); + out.write(">"); + //out.newLine(); // PATCHED, jjg + state = IN_BODY; + } + + /** + * Finish an empty element tag, such as a META, BASE or LINK tag. + * This is expected to correspond with a startTag. + * @param tag the tag which is being closed. this is only useful for + * validation, it is not written out + * @throws IllegalStateException if this call does not follow startTag + * (stream is not currently inside a tag) + * @throws IOException if there is a problem writing to the underlying stream + */ + public void endEmptyTag(String tag) throws IOException { + if (state != IN_TAG) + throw new IllegalStateException(); + + out.write(">"); + state = IN_BODY; + out.newLine(); + } + + /** + * Write an attribute for a tag. A tag must previously have been started. + * All tag attributes must be written before any body text is written. + * The value will be quoted if necessary when writing it to the underlying + * stream. No check is made that the attribute is valid for the current tag. + * @param name the name of the attribute to be written + * @param value the value of the attribute to be written + * @throws IllegalStateException if the stream is not in a state to + * write attributes -- e.g. if this call does not follow startTag or other + * calls of writteAttr + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeAttr(String name, String value) throws IOException { + if (state != IN_TAG) + throw new IllegalStateException(); + + out.write(" "); + out.write(name); + out.write("="); + boolean alpha = true; + for (int i = 0; i < value.length() && alpha; i++) + alpha = Character.isLetter(value.charAt(i)); + if (!alpha) + out.write("\""); + out.write(value); + if (!alpha) + out.write("\""); + } + + /** + * Write an attribute for a tag. A tag must previously have been started. + * All tag attributes must be written before any body text is written. + * The value will be quoted if necessary when writing it to the underlying + * stream. No check is made that the attribute is valid for the current tag. + * @param name the name of the attribute to be written + * @param value the value of the attribute to be written + * @throws IllegalStateException if the stream is not in a state to + * write attributes -- e.g. if this call does not follow startTag or other + * calls of writteAttr + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeAttr(String name, int value) throws IOException { + writeAttr(name, Integer.toString(value)); + } + + /** + * Write a line of text, followed by a newline. + * The text will be escaped as necessary. + * @param text the text to be written. + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLine(String text) throws IOException { + write(text); + out.newLine(); + } + + /** + * Write body text, escaping it as necessary. + * If this call follows a call of startTag, the open tag will be + * closed -- meaning that no more attributes can be written until another + * tag is started. If the text value is null, the current tag will still + * be closed, but no other text will be written. + * @param text the text to be written, may be null or zero length. + * @throws IOException if there is a problem writing to the underlying stream + */ + public void write(String text) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + + if (text == null) + return; + + // check to see if there are any special characters + boolean specialChars = false; + for (int i = 0; i < text.length() && !specialChars; i++) { + switch (text.charAt(i)) { + case '<': case '>': case '&': + specialChars = true; + } + } + + // if there are special characters write the string character at a time; + // otherwise, write it out as is + if (specialChars) { + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + switch (c) { + case '<': out.write("<"); break; + case '>': out.write(">"); break; + case '&': out.write("&"); break; + default: out.write(c); + } + } + } + else + out.write(text); + } + + /** + * Write a basic HTML entity, such as or { . + * @param entity the entity to write + * @throws IOException if there is a problem writing to the underlying stream + */ + public void writeEntity(String entity) throws IOException { + if (state == IN_TAG) { + out.write(">"); + state = IN_BODY; + } + out.write(entity); + } + + /** + * Write an image tag, using a specified path for the image source attribute. + * @param imagePath the path for the image source + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeImage(String imagePath) throws IOException { + startTag(IMAGE); + writeAttr(SRC, imagePath); + } + + /** + * Write an image tag, using a specified path for the image source attribute. + * @param imageURL the url for the image source + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeImage(URL imageURL) throws IOException { + writeImage(imageURL.toString()); + } + + /** + * Write a hypertext link. + * @param anchor the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(String anchor, String body) throws IOException { + startTag(A); + writeAttr(HREF, anchor); + write(body); + endTag(A); + } + + /** + * Write a hypertext link. + * @param file the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(File file, String body) throws IOException { + startTag(A); + StringBuffer sb = new StringBuffer(); + String path = file.getPath().replace(File.separatorChar, '/'); + if (file.isAbsolute() && !path.startsWith("/")) + sb.append('/'); + sb.append(path); + writeAttr(HREF, sb.toString()); + write(body); + endTag(A); + } + + /** + * Write a hypertext link. + * @param file the target and body for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(File file) throws IOException { + writeLink(file, file.getPath()); + } + + /** + * Write a hypertext link. + * @param url the target for the link + * @param body the body text for the link + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLink(URL url, String body) throws IOException { + startTag(A); + writeAttr(HREF, url.toString()); + write(body); + endTag(A); + } + + /** + * Write the destination marker for a hypertext link. + * @param anchor the destination marker for hypertext links + * @param body the body text for the marker + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeLinkDestination(String anchor, String body) throws IOException { + startTag(A); + writeAttr(NAME, anchor); + write(body); + endTag(A); + } + + /** + * Write a parameter tag. + * @param name the name of the parameter + * @param value the value of the parameter + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeParam(String name, String value) throws IOException { + startTag(PARAM); + writeAttr(NAME, name); + writeAttr(VALUE, value); + } + + /** + * Write a style attribute. + * @param value the value for the style atrtribute + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeStyleAttr(String value) throws IOException { + writeAttr(STYLE, value); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(I18NResourceBundle i18n, String key) throws IOException { + write(i18n.getString(key)); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @param arg an argument to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(I18NResourceBundle i18n, String key, Object arg) throws IOException { + write(i18n.getString(key, arg)); + } + + /** + * Write a localized message, using a specified resource bundle. + * @param i18n the resource bundle used to localize the message + * @param key the key for the message to be localized + * @param args arguments to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void write(I18NResourceBundle i18n, String key, Object[] args) throws IOException { + write(i18n.getString(key, args)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key) throws IOException { + write(i18n.getString(key)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @param arg an argument to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key, Object arg) throws IOException { + write(i18n.getString(key, arg)); + } + + /** + * Write a localized message, using the default resource bundle. + * @param key the key for the message to be localized + * @param args arguments to be formatted into the localized message + * @throws IOException if there is a problem closing the underlying stream + */ + public void writeI18N(String key, Object[] args) throws IOException { + write(i18n.getString(key, args)); + } + + /** The HTML "a" tag. */ + public static final String A = "a"; + /** The HTML "align" attribute. */ + public static final String ALIGN = "align"; + /** The HTML "b" tag. */ + public static final String B = "b"; + /** The HTML "body" tag. */ + public static final String BODY = "body"; + /** The HTML "border" attribute. */ + public static final String BORDER = "border"; + /** The HTML "br" tag. */ + public static final String BR = "br"; + /** The HTML "classid" attribute. */ + public static final String CLASSID = "classid"; + /** The HTML "code" tag. */ + public static final String CODE = "code"; + /** The HTML "color" attribte. */ + public static final String COLOR = "color"; + /** The HTML "col" attribute value. */ + public static final String COL = "col"; + /** The HTML "font" tag. */ + public static final String FONT = "font"; + /** The HTML "h1" tag. */ + public static final String H1 = "h1"; + /** The HTML "h2" tag. */ + public static final String H2 = "h2"; + /** The HTML "h3" tag. */ + public static final String H3 = "h3"; + /** The HTML "h4" tag. */ + public static final String H4 = "h4"; + /** The HTML "head" tag. */ + public static final String HEAD = "head"; + /** The HTML "href" attribute. */ + public static final String HREF = "href"; + /** The HTML "html" tag. */ + public static final String HTML = "html"; + /** The HTML "hr" tag. */ + public static final String HR = "hr"; + /** The HTML "i" tag. */ + public static final String I = "i"; + /** The HTML "image" tag. */ + public static final String IMAGE = "image"; + /** The HTML "left" attribute value. */ + public static final String LEFT = "left"; + /** The HTML "li" tag. */ + public static final String LI = "li"; + /** The HTML "link" tag. */ + public static final String LINK = "link"; + /** The HTML "name" attribute. */ + public static final String NAME = "name"; + /** The HTML "object" tag. */ + public static final String OBJECT = "object"; + /** The HTML "p" tag. */ + public static final String PARAM = "param"; + /** The HTML "param" tag. */ + public static final String P = "p"; + /** The HTML "rel" attribute value. */ + public static final String REL = "rel"; + /** The HTML "right" attribute value. */ + public static final String RIGHT = "right"; + /** The HTML "row" attribute value. */ + public static final String ROW = "row"; + /** The HTML "small" tag. */ + public static final String SMALL = "small"; + /** The HTML "src" attribute. */ + public static final String SRC = "src"; + /** The HTML "scope" attribute. */ + public static final String SCOPE = "scope"; + /** The HTML "style" attribute. */ + public static final String STYLE = "style"; + /** The HTML "table" tag. */ + public static final String TABLE = "table"; + /** The HTML "td" tag. */ + public static final String TD = "td"; + /** The HTML "title"attribute. */ + public static final String TITLE = "title"; + /** The HTML "th" tag. */ + public static final String TH = "th"; + /** The HTML "top" attribute value. */ + public static final String TOP = "top"; + /** The HTML "tr" tag. */ + public static final String TR = "tr"; + /** The HTML "type" attribute. */ + public static final String TYPE = "type"; + /** The HTML "ul" tag. */ + public static final String UL = "ul"; + /** The HTML "valign" attribute. */ + public static final String VALIGN = "valign"; + /** The HTML "value" attribute. */ + public static final String VALUE = "value"; + + + private BufferedWriter out; + private int state; + private I18NResourceBundle i18n; + private static final int IN_TAG = 1; + private static final int IN_BODY = 2; +}
--- a/test/jtreg/com/sun/javatest/diff/Main.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/diff/Main.java Sun Nov 09 22:29:59 2008 +0100 @@ -33,20 +33,12 @@ package com.sun.javatest.diff; import com.sun.javatest.regtest.BadArgs; -import java.io.BufferedWriter; import java.io.File; -import java.io.FileWriter; -import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; -import com.sun.javatest.Status; -import com.sun.javatest.TestResult; -import com.sun.javatest.TestSuite; -import com.sun.javatest.WorkDirectory; import com.sun.javatest.regtest.AntOptionDecoder; import com.sun.javatest.regtest.Option; import com.sun.javatest.regtest.OptionDecoder; @@ -58,29 +50,24 @@ * Main entry point for jtdiff. */ public class Main { - - /** - * Exception to report a problem while executing in Main. - */ - public static class Fault extends Exception { - static final long serialVersionUID = 1607979458544175906L; - Fault(I18NResourceBundle i18n, String s, Object... args) { - super(i18n.getString(s, args)); - } - } //---------- command line option decoding ---------------------------------- - + private static final String COMPARE = "compare"; private static final String OUTPUT = "output"; private static final String DOC = "doc"; private static final String FILES = "files"; - + Option[] options = { - new Option(NONE, COMPARE, "r", "reason") { + new Option(NONE, COMPARE, "r", "r", "reason") { public void process(String opt, String arg) { includeReason = true; } }, + new Option(NONE, COMPARE, "s", "s", "super") { + public void process(String opt, String arg) { + superMode = true; + } + }, new Option(OLD, OUTPUT, "o", "o", "outFile") { public void process(String opt, String arg) { outFile = new File(arg); @@ -136,7 +123,7 @@ } finally { out.flush(); } - + if (!ok) { // take care not to exit if GUI might be around, // and take care to ensure JavaTestSecurityManager will @@ -159,16 +146,16 @@ exit(3); } } // main() - + public Main() { this(new PrintWriter(System.out, true), new PrintWriter(System.err, true)); } - + public Main(PrintWriter out, PrintWriter err) { this.out = out; this.err = err; } - + /** * Decode command line args and perform the requested operations. * @param args An array of args, such as might be supplied on the command line. @@ -178,141 +165,55 @@ */ public final boolean run(String[] args) throws BadArgs, Fault, InterruptedException { new OptionDecoder(options).decodeArgs(args); - + + if (superMode) { + if (fileArgs.size() != 1 || !fileArgs.get(0).isDirectory()) + throw new Fault(i18n, "main.bad.super.dir"); + if (format != null) + throw new Fault(i18n, "main.bad.super.format"); + } + return run(); } - + private boolean run() throws Fault, InterruptedException { - if (fileArgs.size() == 0 && help == null) { + if (fileArgs.size() == 0 && !superMode && help == null) { help = new Help(options); help.setCommandLineHelpQuery(null); } - + if (help != null) { help.show(out); return true; } - - List<DiffReader> list = new ArrayList<DiffReader>(); - for (File f: fileArgs) - list.add(open(f)); - - PrintWriter prevOut = out; - if (outFile != null) { - try { - out = new PrintWriter(new BufferedWriter(new FileWriter(outFile))); // FIXME don't want to use PrintWriter - } catch (IOException e) { - throw new Fault(i18n, "main.cantOpenFile", outFile, e); - } - } - - try { - initComparator(); - - initReporter(); - reporter.setTitle(title); - reporter.setComparator(comparator); - reporter.setReaders(list); - List<int[]> testCounts = new ArrayList<int[]>(); - MultiMap<String,TestResult> table = new MultiMap<String,TestResult>(); - for (DiffReader r: list) { - int index = table.add(r.getFile().getPath()); - int[] counts = new int[Status.NUM_STATES]; - for (TestResult tr: r) { - table.add(index, tr.getTestName(), tr); - counts[tr.getStatus().getType()]++; - } - testCounts.add(counts); - } - - reporter.setTestCounts(testCounts); - - try { - reporter.write(table); - } catch (IOException e) { - throw new Fault(i18n, "main.ioError", e); - } + Diff d; + if (superMode) + d = new SuperDiff(fileArgs.get(0)); + else + d = new StandardDiff(fileArgs); - return (reporter.diffs == 0); - } finally { - if (out != prevOut) { -// try { - out.close(); -// } catch (IOException e) { -// throw new Fault(i18n, "main.ioError", e); -// } - out = prevOut; - } - } - } - - private void initFormat() { - if (format == null && outFile != null) { - String name = outFile.getName(); - int dot = name.lastIndexOf("."); - if (dot != -1) - format = name.substring(dot + 1).toLowerCase(); - } + d.includeReason = includeReason; + d.format = format; + d.title = title; + + return d.report(outFile); } - - private void initReporter() throws Fault { - if (reporter == null) { - try { - initFormat(); - if (format != null && format.equals("html")) - reporter = new HTMLReporter(out); - if (reporter == null) - reporter = new SimpleReporter(out); - } catch (IOException e) { - throw new Fault(i18n, "main.cantOpenReport", e); - } - } - } - - private void initComparator() { - if (comparator == null) - comparator = new StatusComparator(includeReason); - } - - private DiffReader open(File f) throws Fault { - if (!f.exists()) - throw new Fault(i18n, "main.cantFindFile", f); - - try { - if (WorkDirectoryReader.accepts(f)) - return new WorkDirectoryReader(f); - - if (ReportReader.accepts(f)) - return new ReportReader(f); - - throw new Fault(i18n, "main.unrecognizedFile", f); - - } catch (TestSuite.Fault e) { - throw new Fault(i18n, "main.cantOpenFile", f, e); - } catch (WorkDirectory.Fault e) { - throw new Fault(i18n, "main.cantOpenFile", f, e); - } catch (IOException e) { - throw new Fault(i18n, "main.cantOpenFile", f, e); - } - - } - + private static void exit(int exitCode) { System.exit(exitCode); } - + private PrintWriter out; private PrintWriter err; - private Comparator<TestResult> comparator; - private Reporter reporter; - + private boolean includeReason; private String format; private String title; private File outFile; private List<File> fileArgs = new ArrayList<File>(); + private boolean superMode; private Help help; - + private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Main.class); }
--- a/test/jtreg/com/sun/javatest/diff/MultiMap.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/diff/MultiMap.java Sun Nov 09 22:29:59 2008 +0100 @@ -38,26 +38,26 @@ */ public class MultiMap<K,V> implements Map<K, MultiMap.Entry<V>> { public static class Entry<V> { - + private Entry(MultiMap<?,?> t) { table = t; } - + V get(int index) { return (index < list.size() ? list.get(index) : null); } - + int getSize() { return table.getColumns(); } - + void put(int index, V value) { if (index >= table.getColumns()) throw new IndexOutOfBoundsException(); - + if (list == null) list = new ArrayList<V>(index); - + if (index < list.size()) list.set(index, value); else { @@ -66,7 +66,7 @@ list.add(value); } } - + boolean allEqual(Comparator<V> c) { if (list.size() == 0) return true; @@ -79,96 +79,95 @@ } return true; } - + private List<V> list; private MultiMap<?,?> table; } - - /** Creates a new instance of DiffTable */ + + /** Creates a new instance of MultiMap */ public MultiMap() { names = new ArrayList<String>(); map = new TreeMap<K, Entry<V>>(); } - + int getColumns() { return names.size(); } - + String getColumnName(int index) { return names.get(index); } - - int add(String name) { + + int addColumn(String name) { names.add(name); return names.size() - 1; } - - void add(int index, K k, V v) { + + void addColumn(String name, Map<K, V> map) { + addColumn(name, map.entrySet()); + } + + void addColumn(String name, Iterable<Map.Entry<K,V>> iter) { + int index = addColumn(name); + for (Map.Entry<K,V> e: iter) + addRow(index, e.getKey(), e.getValue()); + } + + void addRow(int index, K k, V v) { Entry<V> de = get(k); if (de == null) put(k, de = new Entry<V>(this)); de.put(index, v); - } - - void add(String name, Map<K, V> map) { - add(name, map.entrySet()); - } - - void add(String name, Iterable<Map.Entry<K,V>> iter) { - int index = add(name); - for (Map.Entry<K,V> e: iter) - add(index, e.getKey(), e.getValue()); - } - + public int size() { return map.size(); } - + public Entry<V> get(Object path) { return map.get(path); } - + public boolean isEmpty() { return map.isEmpty(); } - + public boolean containsKey(Object key) { return map.containsKey(key); } - + public boolean containsValue(Object value) { return map.containsValue(value); } - + public Entry<V> put(K key, Entry<V> value) { return map.put(key, value); } - + public Entry<V> remove(Object key) { return map.remove(key); } - + public void putAll(Map<? extends K, ? extends Entry<V>> t) { map.putAll(t); } - + public void clear() { map.clear(); } - + public Set<Map.Entry<K, Entry<V>>> entrySet() { return map.entrySet(); } - + public Set<K> keySet() { return map.keySet(); } - + public Collection<Entry<V>> values() { return map.values(); } - + private List<String> names; private TreeMap<K, Entry<V>> map; }
--- a/test/jtreg/com/sun/javatest/diff/ReportReader.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/diff/ReportReader.java Sun Nov 09 22:29:59 2008 +0100 @@ -39,28 +39,28 @@ import java.util.List; /** - * Read a set of test results from summary.txt, possibly located in a + * Read a set of test results from summary.txt, possibly located in a * report directory. */ public class ReportReader implements DiffReader { - private static final String SUMMARY_TXT = "summary.txt"; - + private static final String SUMMARY_TXT = "summary.txt"; + public static boolean accepts(File f) { if (!f.exists()) return false; - + if (f.isFile() && f.getName().equals(SUMMARY_TXT)) return true; - + if (f.isDirectory() && new File(f, SUMMARY_TXT).exists()) return true; - + if (f.isDirectory() && new File(new File(f, "text"), SUMMARY_TXT).exists()) return true; - + return false; } - + /** Creates a new instance of SummaryReader */ public ReportReader(File file) { this.file = file; @@ -69,11 +69,7 @@ public File getFile() { return file; } - - public File getWorkDirectory() { - return null; - } - + public String getFileType() { if (file != null && file.isDirectory()) return i18n.getString("report.reportDir"); @@ -81,10 +77,14 @@ return i18n.getString("report.reportFile"); } + public File getWorkDirectory() { + return null; + } + public Iterator<TestResult> iterator() { return readSummary().iterator(); } - + private List<TestResult> readSummary() { List<TestResult> list = new ArrayList<TestResult>(); File root = getRoot(); @@ -97,7 +97,7 @@ f = new File(new File(file, "text"), SUMMARY_TXT); else throw new IllegalStateException(); - + try { BufferedReader in = new BufferedReader(new FileReader(f)); String line; @@ -113,14 +113,14 @@ } return list; } - + private File getRoot() { return UNKNOWN; } - + private static File UNKNOWN = new File("unknown"); - + private File file; - + private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(WorkDirectoryReader.class); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jtreg/com/sun/javatest/diff/StandardDiff.java Sun Nov 09 22:29:59 2008 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.javatest.diff; + +import java.io.File; +import java.util.List; + +public class StandardDiff extends Diff { + StandardDiff(List<File> files) { + this.files = files; + } + + @Override + public boolean report(File outFile) throws Fault, InterruptedException { + return diff(files, outFile); + } + + List<File> files; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jtreg/com/sun/javatest/diff/SuperDiff.java Sun Nov 09 22:29:59 2008 +0100 @@ -0,0 +1,342 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.javatest.diff; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import com.sun.javatest.util.I18NResourceBundle; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import static com.sun.javatest.util.HTMLWriter.*; + +class SuperDiff extends Diff { + SuperDiff(File dir) { + table = new SuperTable(dir, resultPath); + } + + @Override + public boolean report(File outDir) throws Fault, InterruptedException { + baseTitle = title; + boolean ok = true; + for (YearDay yearDay: table.getRecentKeys(historySize)) + ok &= diffPlatforms(yearDay, outDir); + for (String platform : table.platforms) { + ok &= diffHistory(platform, outDir); + } + writeIndex(outDir, baseTitle); + return ok; + } + + protected boolean diff(List<File> files, File outFile, String title) throws Fault, InterruptedException { + this.title = title; + reporter = null; + return diff(files, outFile); + } + + @Override + protected void initReporter() throws Fault { + try { + reporter = new SuperReporter(out); + } catch (IOException e) { + throw new Fault(i18n, "main.cantOpenReport", e); + } + } + + private boolean diffPlatforms(YearDay yearDay, File outDir) throws Fault, InterruptedException { + Map<String, File> pMap = table.get(yearDay); + List<File> pDirs = new ArrayList<File>(); + for (String platform : table.platforms) { + File dir = pMap.get(platform); + if (dir != null) { + pDirs.add(dir); + } + } + File file = new File(outDir, yearDay.year + "_" + yearDay.dayOfYear + ".html"); + platformIndex.put(yearDay.toDateString(monthDayFormat), file); + String prefix = baseTitle == null ? "" : baseTitle + ": "; + return diff(pDirs, file, prefix + yearDay.toDateString(mediumDateFormat)); // I18N a better title? + } + + private boolean diffHistory(String platform, File outDir) throws Fault, InterruptedException { + List<File> pDirs = new ArrayList<File>(); + for (YearDay yearDay: table.getRecentKeys(historySize, platform)) { + pDirs.add(table.get(yearDay).get(platform)); + } + File file = new File(outDir, platform + ".html"); + historyIndex.put(platform, file); + String prefix = baseTitle == null ? "" : baseTitle + ": "; + return diff(pDirs, file, prefix + platform);// I18N a better title? + } + + private void writeIndex(File outDir, String title) throws Fault { + PrintWriter out; + try { + out = new PrintWriter(new BufferedWriter(new FileWriter(new File(outDir, "index.html")))); + } catch (IOException e) { + throw new Fault(i18n, "main.cantOpenReport", e); + } + + try { + SuperReporter r = new SuperReporter(out); + r.writeMainIndex(title); + } catch (IOException e) { + throw new Fault(i18n, "main.ioError", e); + } finally { + out.close(); + } + } + + protected String resultPath = System.getProperty("jtdiff.super.testResults", "JTreport/text/summary.txt"); + protected int historySize = Integer.getInteger("jtdiff.super.history", 21); + + private SuperTable table; + private String baseTitle; + private Map<String,File> historyIndex = new LinkedHashMap<String,File>(); + private Map<String,File> platformIndex = new LinkedHashMap<String,File>(); + + private static DateFormat monthDayFormat = new SimpleDateFormat("MMM d"); + private static DateFormat mediumDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM); + private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Main.class); + + static class Info { + Info(String platform, Date date) { + this.platform = platform; + this.date = date; + } + + final String platform; + final Date date; + } + + class SuperReporter extends HTMLReporter { + SuperReporter(Writer out) throws IOException { + super(out); + } + + protected void writeIndexTableInfoHeadings() throws IOException { + out.startTag(TH); + out.writeI18N("super.th.platform"); + out.endTag(TH); + out.startTag(TH); + out.writeI18N("super.th.date"); + out.endTag(TH); + } + + protected void writeIndexTableInfoValues(String path) throws IOException { + Info info = table.getInfo(path); + out.startTag(TD); + if (info != null) + out.write(info.platform); + out.endTag(TD); + out.startTag(TD); + if (info != null) + out.write(monthDayFormat.format(info.date)); + out.endTag(TH); + } + + void writeMainIndex(String title) throws IOException { + startReport(title); + + out.startTag(H1); + out.write(baseTitle); + out.endTag(H1); + + writeMainIndexList(i18n.getString("super.platforms"), platformIndex); + writeMainIndexList(i18n.getString("super.history"), historyIndex); + + endReport(); + } + + void writeMainIndexList(String head, Map<String,File> map) throws IOException { + out.startTag(H2); + out.write(head); + out.endTag(H2); + out.startTag(P); + String comma = ""; + for (Map.Entry<String,File> e: map.entrySet()) { + out.write(comma); + out.startTag(A); + out.writeAttr(HREF, e.getValue().getName()); + String nbsp = ""; + for (String s: e.getKey().split(" ")) { + out.writeEntity(nbsp); + out.write(s); + nbsp = " "; + } + out.endTag(A); + comma = ", "; + } + } + } + + static class SuperTable extends TreeMap<YearDay, Map<String, File>> { + + static final long serialVersionUID = 5933594140534747584L; + + SuperTable(File inDir, String resultPath) { + super(); + for (File pDir : inDir.listFiles()) { + if (!pDir.isDirectory()) { + continue; + } + for (File yDir : pDir.listFiles()) { + if (!yDir.isDirectory()) { + continue; + } + for (File dDir : yDir.listFiles()) { + if (!dDir.isDirectory()) { + continue; + } + File resultDir = new File(dDir, resultPath); + if (resultDir.exists()) { + add(pDir.getName(), yDir.getName(), dDir.getName(), resultDir); + } + } + } + } + } + + private void add(String platform, String year, String day, File dir) { + platforms.add(platform); + YearDay yd = new YearDay(year, day); + Map<String, File> pMap = get(yd); + if (pMap == null) { + pMap = new HashMap<String, File>(); + put(yd, pMap); + } + pMap.put(platform, dir); + + Date date; + try { + Calendar c = Calendar.getInstance(); + c.clear(); + c.set(Calendar.YEAR, Integer.parseInt(year)); + c.set(Calendar.DAY_OF_YEAR, Integer.parseInt(day)); + date = c.getTime(); + } catch (NumberFormatException e) { + date = null; + } + infoTable.put(dir.getPath(), new Info(platform, date)); + } + + List<YearDay> getRecentKeys(int n) { + return getRecentKeys(n, null); + } + + List<YearDay> getRecentKeys(int n, String platform) { + LinkedList<YearDay> results = new LinkedList<YearDay>(); + List<YearDay> keys = new ArrayList<YearDay>(keySet()); + for (ListIterator<YearDay> iter = keys.listIterator(keys.size()); + iter.hasPrevious() && results.size() < n; ) { + YearDay key = iter.previous(); + if (platform == null || get(key).get(platform) != null) + results.addFirst(key); + } + return results; + } + + Info getInfo(String path) { + return infoTable.get(path); + } + + final Set<String> platforms = new TreeSet<String>(); + final Map<String,Info> infoTable = new HashMap<String, Info>(); + } + + static class YearDay implements Comparable<YearDay> { + YearDay(String year, String dayOfYear) { + year.getClass(); + dayOfYear.getClass(); + this.year = year; + this.dayOfYear = dayOfYear; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof YearDay)) + return false; + YearDay ydo = (YearDay) o; + return year.equals(ydo.year) && dayOfYear.equals(ydo.dayOfYear); + } + + @Override + public int hashCode() { + return year.hashCode() * 37 + dayOfYear.hashCode(); + } + + //@Override + public int compareTo(YearDay o) { + int c = compare(year, o.year); + return (c == 0 ? compare(dayOfYear, o.dayOfYear) : c); + } + + public String toString() { + return year + ":" + dayOfYear; + } + + public Date asDate() { + try { + Calendar c = Calendar.getInstance(); + c.clear(); + c.set(Calendar.YEAR, Integer.parseInt(year)); + c.set(Calendar.DAY_OF_YEAR, Integer.parseInt(dayOfYear)); + return c.getTime(); + } catch (NumberFormatException e) { + return null; + } + } + + public String toDateString(DateFormat f) { + Date d = asDate(); + return (d == null ? toString() : f.format(d)); + } + + private int compare(String left, String right) { + return left.compareTo(right); + } + + final String year; + final String dayOfYear; + } + +}
--- a/test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/diff/WorkDirectoryReader.java Sun Nov 09 22:29:59 2008 +0100 @@ -48,12 +48,12 @@ public static boolean accepts(File f) { return WorkDirectory.isWorkDirectory(f); } - + /** Creates a new instance of WorkDirectoryReader */ - public WorkDirectoryReader(File file) + public WorkDirectoryReader(File file) throws FileNotFoundException, WorkDirectory.Fault, TestSuite.Fault { this.file = file; - + // Because regtest testsuites don't contain testsuite.jtt // files, we can't use the standard WorkDirectory.open call. File tsp = getTestSuitePath(file); @@ -63,31 +63,31 @@ } else wd = WorkDirectory.open(file); } - + + public File getFile() { + return file; + } + public String getFileType() { return i18n.getString("wd.name"); } - - public File getFile() { - return file; - } - + public File getWorkDirectory() { return wd.getRoot(); } - + @SuppressWarnings("unchecked") public Iterator<TestResult> iterator() { TestResultTable trt = wd.getTestResultTable(); trt.waitUntilReady(); return trt.getIterator(); } - + private static File getTestSuitePath(File workDir) { File f = new File(new File(workDir, "jtData"), "testsuite"); - if (!f.exists()) + if (!f.exists()) return null; - + InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(f)); @@ -105,9 +105,9 @@ return null; } } - + private File file;; private WorkDirectory wd; - + private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(WorkDirectoryReader.class); }
--- a/test/jtreg/com/sun/javatest/diff/i18n.properties Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/diff/i18n.properties Sun Nov 09 22:29:59 2008 +0100 @@ -23,6 +23,10 @@ # have any questions. # +diff.cantOpenFile=Cannot open file {0}: {1} +diff.cantOpenReport=Cannot open report: {0} +diff.ioError=Error: {0} + help.cantFindReleaseNotes= help.onlineHelp.pleaseWait=Loading online help ... help.releaseNotes= @@ -42,8 +46,21 @@ help.compare.name=Compare Options help.compare.desc= -help.compare.reason.desc=Include the reason string in the comparison, as well as \ +help.compare.r.desc=Include the reason string in the comparison, as well as \ the type (i.e. Passed, Failed, etc.) +help.compare.s.desc=Perform a "super-diff" looking for result sets within \ + a directory hierarchy. The hierarchy must be arranged as \ + follows: PATH/PLATFORM/YEAR/DAY_OF_YEAR/TEST_RESULTS, where PATH is \ + given by the single directory argument, PLATFORM is the name of the \ + platform on which the tests were run, YEAR and DAY_OF_YEAR are numbers \ + identifying when the tests were run, and TESTSUITE_RESULTS is a fixed string \ + identifying when to find the result set in the hierarchy. The default \ + is "JTreport/text/summary.txt", but it can be set to a different value by \ + setting the system property "jtdiff.super.testResults". It may identify any \ + source of results acceptable to a standard invocation of jtdiff. \ + Set system property jtdiff.html.compact=true for a more output format, with \ + symbols replacing the words "pass" (check mark), "fail" (cross), "error" \ + (cross in a circle), and "not run" (horizontal bar). help.doc.name=Help Options help.doc.desc=Options for additional help and information @@ -76,6 +93,10 @@ html.fail=fail html.notRun=not run html.pass=pass +html.error.compact=⊗ +html.fail.compact=× +html.notRun.compact=— +html.pass.compact=√ html.head.differences=Differences html.head.notitle=jtdiff results @@ -94,6 +115,8 @@ html.th.type=Type main.badArgs=Error: {0} +main.bad.super.dir=Bad directory argument for "super" mode +main.bad.super.format=Cannot specify format in "super" mode main.cantFindFile=Cannot find file: {0} main.cantOpenFile=Cannot open file {0}: {1} main.cantOpenReport=Cannot open report: {0} @@ -123,3 +146,8 @@ {6,choice,0#|0<not run: {6,number}} wd.name=Work Directory + +super.history=Comparison of recent results by platform +super.platforms=Comparison across platforms by date +super.th.date=Date +super.th.platform=Platform
--- a/test/jtreg/com/sun/javatest/regtest/Main.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/regtest/Main.java Sun Nov 09 22:29:59 2008 +0100 @@ -83,7 +83,7 @@ * JavaTest entry point to be used to access regression extensions. */ public class Main { - + /** * Exception to report a problem while executing in Main. */ @@ -93,14 +93,14 @@ super(i18n.getString(s, args)); } } - + public static final String MAIN = "main"; // main set of options public static final String SELECT = "select"; // test selection options public static final String JDK = "jdk"; // specify JDK to use public static final String MODE = "mode"; // sameVM or otherVM public static final String VERBOSE = "verbose"; // verbose controls public static final String DOC = "doc"; // help or doc info - + Option[] options = { new Option(OPT, VERBOSE, "verbose", "v", "verbose") { @Override @@ -122,49 +122,49 @@ childArgs.add(opt); } }, - + new Option(NONE, VERBOSE, "verbose", "v1") { public void process(String opt, String arg) { verbose = Verbose.SUMMARY; childArgs.add(opt); } }, - + new Option(NONE, VERBOSE, "verbose", "va") { public void process(String opt, String arg) { verbose = Verbose.ALL; childArgs.add(opt); } }, - + new Option(NONE, VERBOSE, "verbose", "vp") { public void process(String opt, String arg) { verbose = Verbose.PASS; childArgs.add(opt); } }, - + new Option(NONE, VERBOSE, "verbose", "vf") { public void process(String opt, String arg) { verbose = Verbose.FAIL; childArgs.add(opt); } }, - + new Option(NONE, VERBOSE, "verbose", "ve") { public void process(String opt, String arg) { verbose = Verbose.ERROR; childArgs.add(opt); } }, - + new Option(NONE, VERBOSE, "verbose", "vt") { public void process(String opt, String arg) { verbose = Verbose.TIME; childArgs.add(opt); } }, - + new Option(NONE, DOC, "", "t", "tagspec") { public void process(String opt, String arg) { if (help == null) @@ -172,7 +172,7 @@ help.setTagSpec(true); } }, - + new Option(NONE, DOC, "", "n", "relnote") { public void process(String opt, String arg) { if (help == null) @@ -180,15 +180,15 @@ help.setReleaseNotes(true); } }, - + new Option(OLD, MAIN, "", "w", "workDir") { public void process(String opt, String arg) { - + workDirArg = new File(arg); childArgs.add("-w:" + workDirArg.getAbsolutePath()); } }, - + new Option(OPT, MAIN, "", "retain") { @Override public String[] getChoices() { @@ -204,34 +204,40 @@ childArgs.add(opt); } }, - + new Option(OLD, MAIN, "", "r", "reportDir") { public void process(String opt, String arg) { reportDirArg = new File(arg); childArgs.add("-r:" + reportDirArg.getAbsolutePath()); } }, - - new Option(NONE, MAIN, null, "ro", "reportOnly") { + + new Option(NONE, MAIN, "ro-nr", "ro", "reportOnly") { public void process(String opt, String arg) { reportOnlyFlag = true; } }, - + + new Option(NONE, MAIN, "ro-nr", "nr", "noreport") { + public void process(String opt, String arg) { + noReportFlag = true; + } + }, + new Option(STD, MAIN, "", "timeout", "timeoutFactor") { public void process(String opt, String arg) { timeoutFactorArg = arg; childArgs.add(opt); } }, - + new Option(STD, MAIN, "", "dir") { public void process(String opt, String arg) { baseDirArg = new File(arg); childArgs.add("-dir:" + baseDirArg.getAbsolutePath()); } }, - + new Option(STD, SELECT, "", "status") { @Override public String[] getChoices() { @@ -242,29 +248,29 @@ childArgs.add(opt); } }, - + new Option(STD, SELECT, "", "exclude", "Xexclude") { public void process(String opt, String arg) { File f = new File(arg); excludeListArgs.add(f); - childArgs.add(f.getAbsolutePath()); + childArgs.add("-exclude:" + f.getAbsolutePath()); } }, - + new Option(NONE, MAIN, null, "startHttpd") { public void process(String opt, String arg) { httpdFlag = true; childArgs.add(opt); } }, - + new Option(OLD, MAIN, "", "o", "observer") { public void process(String opt, String arg) { observerClassName = arg; childArgs.add(opt); } }, - + new Option(OLD, MAIN, "", "od", "observerDir", "op", "observerPath") { public void process(String opt, String arg) { arg = arg.trim(); @@ -279,20 +285,20 @@ childArgs.add("-op:" + filesToAbsolutePath(pathToFiles(arg))); } }, - + new Option(NONE, MAIN, null, "g", "gui") { public void process(String opt, String arg) { guiFlag = true; childArgs.add(opt); } }, - + new Option(NONE, MAIN, null, "c", "check") { public void process(String opt, String arg) { checkFlag = true; } }, - + // deprecated new Option(NONE, MAIN, "ignore", "noignore") { public void process(String opt, String arg) { @@ -300,7 +306,7 @@ childArgs.add(opt); } }, - + new Option(STD, MAIN, "ignore", "ignore") { @Override public String[] getChoices() { @@ -323,69 +329,69 @@ throw new BadArgs(i18n, "main.unknownIgnore", arg); } }, - + new Option(NONE, SELECT, "a-m", "a", "automatic", "automagic") { public void process(String opt, String arg) { keywordsExprArg = combineKeywords(keywordsExprArg, AUTOMATIC); childArgs.add(opt); } }, - + new Option(NONE, SELECT, "a-m", "m", "manual") { public void process(String opt, String arg) { keywordsExprArg = combineKeywords(keywordsExprArg, MANUAL); childArgs.add(opt); } }, - + new Option(NONE, SELECT, "shell-noshell", "shell") { public void process(String opt, String arg) { keywordsExprArg = combineKeywords(keywordsExprArg, "shell"); childArgs.add(opt); } }, - + new Option(NONE, SELECT, "shell-noshell", "noshell") { public void process(String opt, String arg) { keywordsExprArg = combineKeywords(keywordsExprArg, "!shell"); childArgs.add(opt); } }, - + new Option(STD, SELECT, null, "bug") { public void process(String opt, String arg) { keywordsExprArg = combineKeywords(keywordsExprArg, "bug" + arg); childArgs.add(opt); } }, - + new Option(STD, SELECT, null, "k", "keywords") { public void process(String opt, String arg) { keywordsExprArg = combineKeywords(keywordsExprArg, "(" + arg + ")"); childArgs.add(opt); } }, - + new Option(NONE, MODE, "svm-ovm", "ovm", "othervm") { public void process(String opt, String arg) { sameJVMFlag = false; childArgs.add(opt); } }, - + new Option(NONE, MODE, "svm-ovm", "s", "svm", "samevm") { public void process(String opt, String arg) { sameJVMFlag = true; childArgs.add(opt); } }, - + new Option(OLD, JDK, "", "jdk", "testjdk") { public void process(String opt, String arg) { jdk = new JDK(arg); } }, - + new Option(STD, JDK, "", "cpa", "classpathappend") { public void process(String opt, String arg) { arg = arg.trim(); @@ -398,73 +404,73 @@ } } }, - + new Option(NONE, JDK, "jit-nojit", "jit") { public void process(String opt, String arg) { jitFlag = true; } }, - + new Option(NONE, JDK, "jit-nojit", "nojit") { public void process(String opt, String arg) { jitFlag = false; } }, - + new Option(WILDCARD, JDK, null, "Xrunjcov") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(NONE, JDK, null, "classic", "green", "native", "hotspot", "client", "server", "d32", "d64") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(OPT, JDK, null, "enableassertions", "ea", "disableassertions", "da") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(NONE, JDK, null, "enablesystemassertions", "esa", "disablesystemassertions", "dsa") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(WILDCARD, JDK, null, "XX", "Xms", "Xmx") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(WILDCARD, JDK, null, "Xint", "Xmixed", "Xcomp") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(STD, JDK, null, "Xbootclasspath") { public void process(String opt, String arg) { testVMOpts.add("-Xbootclasspath:" + filesToAbsolutePath(pathToFiles(arg))); } }, - + new Option(STD, JDK, null, "Xbootclasspath/a") { public void process(String opt, String arg) { testVMOpts.add("-Xbootclasspath/a:" + filesToAbsolutePath(pathToFiles(arg))); } }, - + new Option(STD, JDK, null, "Xbootclasspath/p") { public void process(String opt, String arg) { testVMOpts.add("-Xbootclasspath/p:" + filesToAbsolutePath(pathToFiles(arg))); } }, - + new Option(WILDCARD, JDK, null, "X") { public void process(String opt, String arg) { // This is a change in spec. Previously. -X was used to tunnel @@ -473,20 +479,20 @@ testVMOpts.add(opt); } }, - + new Option(WILDCARD, JDK, null, "D") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(STD, JDK, null, "vmoption") { public void process(String opt, String arg) { if (arg.length() > 0) testVMOpts.add(arg); } }, - + new Option(STD, JDK, null, "vmoptions") { public void process(String opt, String arg) { arg = arg.trim(); @@ -495,7 +501,7 @@ testVMOpts.addAll(Arrays.asList(arg.split("\\s+"))); } }, - + new Option(OLD, JDK, null, "e") { public void process(String opt, String arg) { arg = arg.trim(); @@ -504,25 +510,25 @@ envVarArgs.addAll(Arrays.asList(arg.split(","))); } }, - + new Option(STD, JDK, null, "agentlib") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(STD, JDK, null, "agentpath") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(STD, JDK, null, "javaagent") { public void process(String opt, String arg) { testVMOpts.add(opt); } }, - + new Option(STD, JDK, null, "javacoption") { public void process(String opt, String arg) { arg = arg.trim(); @@ -532,7 +538,7 @@ childArgs.add(opt); } }, - + new Option(STD, JDK, null, "javacoptions") { public void process(String opt, String arg) { arg = arg.trim(); @@ -542,7 +548,7 @@ childArgs.add(opt); } }, - + new Option(STD, JDK, null, "javaoption") { public void process(String opt, String arg) { arg = arg.trim(); @@ -552,7 +558,7 @@ childArgs.add(opt); } }, - + new Option(STD, JDK, null, "javaoptions") { public void process(String opt, String arg) { arg = arg.trim(); @@ -562,7 +568,7 @@ childArgs.add(opt); } }, - + new Option(REST, DOC, "help", "h", "help", "usage") { public void process(String opt, String arg) { if (help == null) @@ -570,7 +576,7 @@ help.setCommandLineHelpQuery(arg); } }, - + new Option(REST, DOC, "help", "onlineHelp") { public void process(String opt, String arg) { if (help == null) @@ -578,7 +584,7 @@ help.setOnlineHelpQuery(arg); } }, - + new Option(NONE, DOC, "help", "version") { public void process(String opt, String arg) { if (help == null) @@ -586,7 +592,7 @@ help.setVersionFlag(true); } }, - + new Option(FILE, MAIN, null) { public void process(String opt, String arg) { File f= new File(arg); @@ -610,7 +616,7 @@ public static final int EXIT_FAULT = 4; /** Unexpected exception occurred. */ public static final int EXIT_EXCEPTION = 5; - + /** * Standard entry point. Only returns if GUI mode is initiated; otherwise, it calls System.exit * with an appropriate exit code. @@ -628,7 +634,7 @@ out.flush(); err.flush(); } - + if (!(m.guiFlag && rc == EXIT_OK)) { // take care not to exit if GUI might be around, // and take care to ensure JavaTestSecurityManager will @@ -654,21 +660,21 @@ exit(EXIT_EXCEPTION); } } // main() - + public Main() { this(new PrintWriter(System.out, true), new PrintWriter(System.err, true)); } - + public Main(PrintWriter out, PrintWriter err) { this.out = out; this.err = err; - + // FIXME: work around bug 6466752 File javatest_jar = findJar("javatest.jar", "lib/javatest.jar", com.sun.javatest.Harness.class); if (javatest_jar != null) System.setProperty("javatestClassDir", javatest_jar.getPath()); } - + /** * Decode command line args and perform the requested operations. * @param args An array of args, such as might be supplied on the command line. @@ -681,7 +687,7 @@ new OptionDecoder(options).decodeArgs(expandAtFiles(args)); return run(); } - + private int run() throws BadArgs, Fault, Harness.Fault, InterruptedException { if (help != null) { guiFlag = help.show(out); @@ -690,7 +696,7 @@ if (sameJVMFlag && !testJavaOpts.isEmpty()) throw new Fault(i18n, "main.cant.mix.samevm.java.options"); - + if (jdk == null) { String s = null; if (!sameJVMFlag) @@ -706,23 +712,23 @@ f = f.getParentFile(); jdk = new JDK(f); } - + if (jitFlag == false) { if (sameJVMFlag) testVMOpts.add("-Djava.compiler="); else envVarArgs.add("JAVA_COMPILER="); } - + if (classPathAppendArg.size() > 0) { // TODO: store this separately in RegressionParameters, instead of in envVars if (!sameJVMFlag) envVarArgs.add("CPAPPEND=" + filesToAbsolutePath(classPathAppendArg)); } - + if (!jdk.exists()) throw new Fault(i18n, "main.jdk.not.found", jdk); - + File baseDir; if (baseDirArg == null) { baseDir = new File(System.getProperty("user.dir")); @@ -731,9 +737,9 @@ throw new Fault(i18n, "main.cantFindFile", baseDirArg); baseDir = baseDirArg.getAbsoluteFile(); } - + List<File> absTestFileArgs = new ArrayList<File>(); - + for (File t: testFileArgs) { if (!t.isAbsolute()) t = new File(baseDir, t.getPath()); @@ -741,13 +747,13 @@ throw new Fault(i18n, "main.cantFindFile", t); absTestFileArgs.add(t); } - + testFileArgs = absTestFileArgs; - + String antFileList = System.getProperty(JAVATEST_ANT_FILE_LIST); if (antFileList != null) antFileArgs.addAll(readFileList(new File(antFileList))); - + if (testSuiteArg == null) { File t; if (testFileArgs.size() > 0) @@ -756,49 +762,57 @@ t = antFileArgs.iterator().next(); else throw new BadArgs(i18n, "main.noTestSuiteOrTests"); - + testSuiteArg = getTestSuite(t); if (testSuiteArg == null) throw new Fault(i18n, "main.cantDetermineTestSuite", t); } - + if (workDirArg == null) { workDirArg = new File("JTwork"); childArgs.add(0, "-w:" + workDirArg.getAbsolutePath()); } - - if (reportDirArg == null) { + + if (reportDirArg == null && !noReportFlag) { reportDirArg = new File("JTreport"); childArgs.add(0, "-r:" + reportDirArg.getAbsolutePath()); } - - makeDir(reportDirArg); + + if (!noReportFlag) + makeDir(reportDirArg); + makeDir(workDirArg); makeDir(new File(workDirArg, "scratch")); - + if (!isThisVMOK()) return execChild(); - + RegressionParameters params = createParameters(); - + checkLockFiles(params.getWorkDirectory().getRoot(), "start"); - + Harness.setClassDir(ProductInfo.getJavaTestClassDir()); - + // Allow keywords to begin with a numeric Keywords.setAllowNumericKeywords(true); - + // Before we install our own security manager (which will restrict access // to the system properties), take a copy of the system properties. TestEnvironment.addDefaultPropTable("(system properties)", System.getProperties()); - + // TODO: take SecurityManager into account for isThisVMOK - if (sameJVMFlag) + if (sameJVMFlag) { RegressionSecurityManager.install(); - + SecurityManager sc = System.getSecurityManager(); + if (sc instanceof RegressionSecurityManager) { + // experimental + ((RegressionSecurityManager) sc).setAllowSetIO(true); + } + } + if (httpdFlag) startHttpServer(); - + if (guiFlag) { showTool(params); return EXIT_OK; @@ -810,7 +824,7 @@ } } } - + /** * Process Win32-style command files for the specified command line * arguments and return the resulting arguments. A command file argument @@ -839,7 +853,7 @@ } return newArgs.toArray(new String[newArgs.size()]); } - + private static void loadCmdFile(String name, List<String> args) throws Fault { Reader r; @@ -871,7 +885,7 @@ } } } - + private static List<File> readFileList(File file) throws Fault { BufferedReader r; @@ -898,7 +912,7 @@ } } } - + private static void writeFileList(File file, List<File> list) throws Fault { try { BufferedWriter out = new BufferedWriter(new FileWriter(file)); @@ -912,21 +926,21 @@ throw new Fault(i18n, "main.cantWrite", file, e); } } - + public int[] getTestStats() { return testStats; } - + private boolean isThisVMOK() { if (reportOnlyFlag || checkFlag || !sameJVMFlag) return true; - + // sameVM tests can use this VM if // - the current directory is the required scratch directory // - the current VM is the required test VM // - there are no outstanding VM options // - there is no classpath append - + File scratchDir = canon(new File(workDirArg, "scratch")); File currDir = canon(new File("")); if (!currDir.equals(scratchDir)) { @@ -934,7 +948,7 @@ System.err.println("dir mismatch: " + currDir + " " + scratchDir); return false; } - + File currJDKHome = canon(new File(System.getProperty("java.home"))); if (currJDKHome.getName().toLowerCase().equals("jre")) currJDKHome = currJDKHome.getParentFile(); @@ -943,53 +957,53 @@ System.err.println("jdk mismatch: " + currJDKHome + " " + jdk + " (" + jdk.getCanonicalFile() + ")"); return false; } - + if (System.getProperty("javatest.child") == null && !testVMOpts.isEmpty()) { if (debugChild) System.err.println("need VM opts: " + testVMOpts); return false; } - + if (classPathAppendArg.size() > 0) { if (debugChild) System.err.println("need classPathAppend: " + classPathAppendArg); return false; } - + return true; } - + // TODO use @file for args? private int execChild() throws Fault { if (System.getProperty("javatest.child") != null) throw new AssertionError(); - + File javatest_jar = findJar("javatest.jar", "lib/javatest.jar", com.sun.javatest.Harness.class); if (javatest_jar == null) throw new Fault(i18n, "main.cantFind.javatest.jar"); - + File jtreg_jar = findJar("jtreg.jar", "lib/jtreg.jar", getClass()); if (jtreg_jar == null) throw new Fault(i18n, "main.cantFind.jtreg.jar"); - + File childJDKHome = jdk.getAbsoluteFile(); File childJava = new File(new File(childJDKHome, "bin"), "java"); File childTools = new File(new File(childJDKHome, "lib"), "tools.jar"); - + File scratchDir = canon(new File(workDirArg, "scratch")); - + List<String> c = new ArrayList<String>(); c.add(childJava.getPath()); - + c.add("-classpath"); List<File> classpath = new ArrayList<File>(); classpath.add(jtreg_jar); classpath.add(childTools); classpath.addAll(classPathAppendArg); c.add(filesToAbsolutePath(classpath)); - + c.addAll(testVMOpts); - + // Tunnel Ant file args separately from command line tests, so that // they can be treated specially in the child VM: invalid files // specified by the user on the command line give an error; @@ -1003,39 +1017,39 @@ throw new Fault(i18n, "main.cantWriteTempFile", e); } } - + for (Map.Entry<?,?> e: System.getProperties().entrySet()) { String name = (String) e.getKey(); if (name.startsWith("javatest.")) c.add("-D" + name + "=" + e.getValue()); } - + c.add("-Djavatest.child=true"); - + c.add(Main.class.getName()); - + for (String o: testVMOpts) c.add("-vmoption:" + o); - + if (baseDirArg == null) c.add("-dir:" + System.getProperty("user.dir")); - + c.addAll(childArgs); - + String[] cmd = c.toArray(new String[c.size()]); File execDir = scratchDir; - + if (debugChild) { System.err.println("Starting JavaTest child"); System.err.println("Dir " + execDir + "; Command " + c); } - + Runtime r = Runtime.getRuntime(); Process p = null; - + try { try { - + // strictly speaking, we do not need to set the CLASSPATH for the child VM, // but we do it to maximize the consistency between sameVM and otherVM env. // See similar code in MainAction for otherVM tests. @@ -1043,46 +1057,46 @@ // because it will not have (and cannot have) the test-specific values. String cp = "CLASSPATH=" + javatest_jar + PATHSEP + jtreg_jar + PATHSEP + jdk.getToolsJar(); - + String[] env = getEnvVars(); String[] env_cp = new String[env.length + 1]; System.arraycopy(env, 0, env_cp, 0, env.length); env_cp[env_cp.length - 1] = cp; - + p = r.exec(cmd, env_cp, execDir); } catch (IOException e) { err.println("cannot start child VM"); return EXIT_FAULT; } - + InputStream childOut = p.getInputStream(); // output stream from process StreamCopier childOutCopier = new StreamCopier(childOut, out); childOutCopier.start(); InputStream childErr = p.getErrorStream(); StreamCopier childErrCopier = new StreamCopier(childErr, err); childErrCopier.start(); - + OutputStream childIn = p.getOutputStream(); // input stream to process if (childIn != null) childIn.close(); - + // wait for the stream copiers to complete childOutCopier.waitUntilDone(); childErrCopier.waitUntilDone(); - + // wait for the process to complete; int exitCode = p.waitFor(); p = null; - + if (debugChild) { System.err.println("JavaTest child process: rc=" + exitCode); } - + childOut.close(); childErr.close(); - + return exitCode; - + } catch (IOException e) { // TODO handle exception return EXIT_EXCEPTION; @@ -1094,7 +1108,7 @@ p.destroy(); } } - + /** * A thread to copy an input stream to an output stream */ @@ -1109,7 +1123,7 @@ in = new BufferedReader(new InputStreamReader(from)); out = to; } - + /** * Set the thread going. */ @@ -1130,32 +1144,32 @@ notifyAll(); } } - + public synchronized boolean isDone() { return done; } - + /** * Blocks until the copy is complete, or until the thread is interrupted */ public synchronized void waitUntilDone() throws InterruptedException { boolean interrupted = false; - + // poll interrupted flag, while waiting for copy to complete while (!(interrupted = Thread.interrupted()) && !done) wait(1000); - + if (interrupted) throw new InterruptedException(); } - + private BufferedReader in; private PrintWriter out; private boolean done; private static int serial; - + } - + private File getTestSuite(File test) { File f = canon(test); if (f.isFile()) @@ -1168,7 +1182,7 @@ // TODO try and default from work directory return null; } - + private String getEnvVar(String name) { for (String arg: envVarArgs) { if (arg.startsWith(name + "=")) @@ -1176,7 +1190,7 @@ } return null; } - + private void makeDir(File dir) throws Fault { // FIXME: I18N if (dir.isDirectory()) @@ -1187,7 +1201,7 @@ throw new Fault(i18n, "main.cantCreateDir", dir); } } - + private static List<File> pathToFiles(String path) { List<File> files = new ArrayList<File>(); for (String f: path.split(File.pathSeparator)) { @@ -1196,7 +1210,7 @@ } return files; } - + private static String filesToAbsolutePath(List<File> files) { StringBuffer sb = new StringBuffer(); for (File f: files) { @@ -1206,7 +1220,7 @@ } return sb.toString(); } - + private static String join(Iterator<?> iter, String sep) { StringBuilder sb = new StringBuilder(); while (iter.hasNext()) { @@ -1216,7 +1230,7 @@ } return sb.toString(); } - + /** * Create a RegressionParameters object based on the values set up by decodeArgs. * @return a RegressionParameters object @@ -1224,26 +1238,26 @@ private RegressionParameters createParameters() throws BadArgs, Fault { File ts = testSuiteArg; File wd = workDirArg; - + try { // create a canonTestFile suite and work dir. RegressionTestSuite testSuite = new RegressionTestSuite(ts); RegressionParameters rp = (RegressionParameters) (testSuite.createInterview()); - + WorkDirectory workDir; if (WorkDirectory.isWorkDirectory(wd)) workDir = WorkDirectory.open(wd, testSuite); else workDir = WorkDirectory.convert(wd, testSuite); rp.setWorkDirectory(workDir); - + rp.setRetainArgs(retainArgs); - + // set up the tests mode, and if specified tests are used, pass in the canonTestFile list. // ensure the tests parameters are root-relative File root = testSuite.getRoot(); List<String> tests = new ArrayList<String>(); - + if (testFileArgs != null) { // In the command line, the canonTestFile args are filenames, probably absolute, // and possibly with non-canonical file separators (e.g. / on Windows). @@ -1261,7 +1275,7 @@ } } } - + // no need to scan ant tests if all test suite selected (i.e. tests == null) if (tests != null && antFileArgs != null && antFileArgs.size() > 0) { TestResultTable trt = workDir.getTestResultTable(); @@ -1279,10 +1293,10 @@ } } } - + if (tests != null && tests.size() > 0) rp.setTests(tests); - + if (keywordsExprArg != null) rp.setKeywordsExpr(keywordsExprArg); rp.setExcludeLists(excludeListArgs.toArray(new File[excludeListArgs.size()])); @@ -1296,7 +1310,7 @@ b[Status.NOT_RUN] = (priorStatusValuesArg.indexOf("notr") != -1); rp.setPriorStatusValues(b); } - + if (concurrencyArg != null) { try { rp.setConcurrency(Integer.parseInt(concurrencyArg)); @@ -1304,7 +1318,7 @@ throw new BadArgs(i18n, "main.badConcurrency"); } } - + if (timeoutFactorArg != null) { try { rp.setTimeoutFactor(Integer.parseInt(timeoutFactorArg)); @@ -1312,10 +1326,10 @@ throw new BadArgs(i18n, "main.badTimeoutFactor"); } } - + if (!rp.isValid()) throw new Fault(i18n, "main.badParams", rp.getErrorMessage()); - + for (String o: testVMOpts) { if (o.startsWith("-Xrunjcov")) { if (!testVMOpts.contains("-XX:+EnableJVMPIInstructionStartEvent")) @@ -1323,23 +1337,23 @@ break; } } - + if (testVMOpts.size() > 0) rp.setTestVMOptions(testVMOpts); - + if (testCompilerOpts.size() > 0) rp.setTestCompilerOptions(testCompilerOpts); - + if (testJavaOpts.size() > 0) rp.setTestJavaOptions(testJavaOpts); - + rp.setCheck(checkFlag); rp.setSameJVM(sameJVMFlag); rp.setEnvVars(getEnvVars()); rp.setJDK(jdk); if (ignoreKind != null) rp.setIgnoreKind(ignoreKind); - + return rp; } catch (TestSuite.Fault f) { f.printStackTrace(); @@ -1359,7 +1373,7 @@ return file.getAbsoluteFile(); } } - + private String getRelativePath(File base, File f) { StringBuilder sb = new StringBuilder(); for ( ; f != null; f = f.getParentFile()) { @@ -1371,18 +1385,18 @@ } return null; } - + /** * Initialize the harness. If we are in verbose mode, add our own observer. */ private Harness createHarness() throws Fault { - + // Set backup parameters; in time this might become more versatile. BackupPolicy backupPolicy = createBackupPolicy(); - + Harness h = new Harness(); h.setBackupPolicy(backupPolicy); - + if (observerClassName != null) { try { Class observerClass; @@ -1413,16 +1427,16 @@ throw new Fault(i18n, "main.obsvrFault", e); } } - + // add our own observer for verbose if (verbose != null) { Harness.Observer observer = new RegressionObserver(verbose, out, err); h.addObserver(observer); } - + return h; } // createHarness() - + /** * Run the harness in batch mode, using the specified parameters. */ @@ -1430,7 +1444,7 @@ throws Fault, Harness.Fault, InterruptedException { try { boolean ok; - + if (reportOnlyFlag) { testStats = new int[Status.NUM_STATES]; for (Iterator iter = getResultsIterator(params); iter.hasNext(); ) { @@ -1443,15 +1457,27 @@ harness.addObserver(new BatchObserver()); ok = harness.batch(params); } - + showResultStats(testStats); - - boolean reportRequired = !Boolean.getBoolean("javatest.noReportRequired"); + + boolean reportRequired = + !noReportFlag && !Boolean.getBoolean("javatest.noReportRequired"); + List<String> reportKinds = + Arrays.asList(System.getProperty("javatest.report.kinds", "html text").split("[ ,]+")); if (reportRequired) { try { Report r = new Report(); Report.Settings s = new Report.Settings(params); - s.setHtmlMainReport(true, true); + if (reportKinds.contains("html")) { + s.setEnableHtmlReport(true); + s.setHtmlMainReport(true, true); + } + if (reportKinds.contains("text")) { + s.setEnablePlainReport(true); + } + if (reportKinds.contains("xml")) { + s.setEnableXmlReport(true); + } s.setFilter(new CompositeFilter(params.getFilters())); r.writeReport(s, reportDirArg); File report = new File(reportDirArg, "report.html"); // std through version 3.* @@ -1463,15 +1489,15 @@ out.println("Error while writing report: " + e); } } - + if (!reportOnlyFlag) out.println("Results written to " + params.getWorkDirectory().getPath()); - + // report a brief msg to System.err as well, in case System.out has // been redirected. if (!ok) err.println(i18n.getString("main.testsFailed")); - + return (testStats[Status.ERROR] > 0 ? EXIT_TEST_ERROR : testStats[Status.FAILED] > 0 ? EXIT_TEST_FAILED : EXIT_OK); @@ -1480,11 +1506,11 @@ err.flush(); } } - + private Iterator getResultsIterator(InterviewParameters params) { TestResultTable trt = params.getWorkDirectory().getTestResultTable(); trt.waitUntilReady(); - + String[] tests = params.getTests(); TestFilter[] filters = params.getFilters(); if (tests == null) @@ -1492,10 +1518,10 @@ else return trt.getIterator(tests, filters); } - + private void showTool(final InterviewParameters params) throws BadArgs { Startup startup = new Startup(); - + try { EventQueue.invokeLater(new Runnable() { public void run() { @@ -1512,13 +1538,13 @@ startup.disposeLater(); } } // showTool() - + private void showResultStats(int[] stats) { int p = stats[Status.PASSED]; int f = stats[Status.FAILED]; int e = stats[Status.ERROR]; int nr = stats[Status.NOT_RUN]; - + String msg; if (p + f + e + nr == 0) msg = i18n.getString("main.noTests"); @@ -1536,7 +1562,7 @@ } out.println(msg); } - + private BackupPolicy createBackupPolicy() { return new BackupPolicy() { public int getNumBackupsToKeep(File file) { @@ -1555,7 +1581,7 @@ private String[] ignoreExtns = StringArray.split(System.getProperty("javatest.backup.ignore", ".jtr")); }; } - + private void startHttpServer() { // start the http server // do this as early as possible, since objects may check @@ -1563,9 +1589,9 @@ // register their handlers HttpdServer server = new HttpdServer(); Thread thr = new Thread(server); - + PageGenerator.setSWName(ProductInfo.getName()); - + // format the date for i18n DateFormat df = DateFormat.getDateInstance(DateFormat.LONG); Date dt = ProductInfo.getBuildDate(); @@ -1574,15 +1600,15 @@ date = df.format(dt); else date = i18n.getString("main.nobDate"); - + PageGenerator.setSWBuildDate(date); PageGenerator.setSWVersion(ProductInfo.getVersion()); - + thr.start(); } - + private String[] getEnvVars() { - + Map<String,String> envVars = new TreeMap<String,String>(); String osName = System.getProperty("os.name").toLowerCase(); if (osName.startsWith("windows")) { @@ -1594,22 +1620,22 @@ addEnvVars(envVars, "PATH=/bin:/usr/bin"); } addEnvVars(envVars, envVarArgs); - + return envVars.values().toArray(new String[envVars.size()]); } - + private void addEnvVars(Map<String,String> table, String list) { addEnvVars(table, list.split(",")); } - + private void addEnvVars(Map<String,String> table, String[] list) { addEnvVars(table, Arrays.asList(list)); } - + private void addEnvVars(Map<String,String> table, List<String> list) { if (list == null) return; - + for (String s: list) { s = s.trim(); if (s.length() == 0) @@ -1625,24 +1651,24 @@ } } } - + private static String combineKeywords(String kw1, String kw2) { return (kw1 == null ? kw2 : kw1 + " & " + kw2); } - + private File findJar(String jarProp, String pathFromHome, Class<?> c) { if (jarProp != null) { String v = System.getProperty(jarProp); if (v != null) return new File(v); } - + if (pathFromHome != null) { String v = System.getProperty("jtreg.home"); if (v != null) return new File(v, pathFromHome); } - + if (c != null) { try { String className = c.getName().replace(".", "/") + ".class"; @@ -1659,10 +1685,10 @@ ignore.printStackTrace(); } } - + return null; } - + /** * Call System.exit, taking care to get permission from the * JavaTestSecurityManager, if it is installed. @@ -1675,7 +1701,7 @@ ((JavaTestSecurityManager) sc).setAllowExit(true); System.exit(exitCode); } - + // This is almost completely dead code; testStats appears unused // so the only use here is error handling, which perhaps can be // folded into RegressionObserver @@ -1683,24 +1709,24 @@ public void startingTestRun(Parameters params) { testStats = new int[Status.NUM_STATES]; } - + public void startingTest(TestResult tr) { } - + public void finishedTest(TestResult tr) { testStats[tr.getStatus().getType()]++; } - + public void stoppingTestRun() { } - + public void finishedTesting() { } - + public void finishedTestRun(boolean allOK) { } - + public void error(String msg) { err.println(i18n.getString("main.error", msg)); } } - + private void checkLockFiles(File workDir, String msg) { // String jc = System.getProperty("javatest.child"); // File jtData = new File(workDir, "jtData"); @@ -1712,12 +1738,12 @@ // } // } } - + //----------member variables----------------------------------------------- - + private PrintWriter out; private PrintWriter err; - + // this first group of args are the "standard" JavaTest args private File testSuiteArg; private File workDirArg; @@ -1732,13 +1758,14 @@ // TODO: consider making this a "pathset" to detect redundant specification // of directories and paths within them. private List<File> antFileArgs = new ArrayList<File>(); - + // these args are jtreg extras private File baseDirArg; private boolean sameJVMFlag; private JDK jdk; private boolean guiFlag; private boolean reportOnlyFlag; + private boolean noReportFlag; private static Verbose verbose; private boolean httpdFlag; private String observerClassName; @@ -1752,28 +1779,28 @@ private List<File> classPathAppendArg = new ArrayList<File>(); private boolean jitFlag = true; private Help help; - - + + // the list of args to be passed down to a child VM private List<String> childArgs = new ArrayList<String>(); - + private int[] testStats; - + private static final String AUTOMATIC = "!manual"; private static final String MANUAL = "manual"; - + private static final String[] DEFAULT_UNIX_ENV_VARS = { "DISPLAY", "HOME", "LANG", "LC_ALL", "LC_TYPE", "LPDEST", "PRINTER", "TZ", "XMODIFIERS" }; - + private static final String[] DEFAULT_WINDOWS_ENV_VARS = { "SystemDrive", "SystemRoot", "windir", "TMP", "TEMP" }; - + private static final String JAVATEST_ANT_FILE_LIST = "javatest.ant.file.list"; - + private static boolean debugChild = Boolean.getBoolean("javatest.regtest.debugChild"); private static final String PATHSEP = System.getProperty("path.separator"); - + private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(Main.class); }
--- a/test/jtreg/com/sun/javatest/regtest/MainAction.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/regtest/MainAction.java Sun Nov 09 22:29:59 2008 +0100 @@ -151,7 +151,7 @@ throw new ParseException(PARSE_SECURE_OTHERVM); } } // init() - + @Override public File[] getSourceFiles() { List<File> l = new ArrayList<File>(); @@ -244,11 +244,11 @@ // available to main and applet actions via the system properties // "test.src" and "test.classes", respectively" List<String> command = new ArrayList<String>(6); - + // some tests are inappropriately relying on the CLASSPATH environment // variable being set, so force the use here. final boolean useCLASSPATH = true; - + if (useCLASSPATH || script.isJDK11()) { command.add("CLASSPATH=" + script.getJavaTestClassPath() + PATHSEP + script.testClassPath()); @@ -263,10 +263,10 @@ command.add("-Dtest.src=" + script.absTestSrcDir()); command.add("-Dtest.classes=" + script.absTestClsDir()); - command.add("-Dtest.vm.opts=" + script.getTestVMOptions()); - command.add("-Dtest.tool.vm.opts=" + script.getTestToolVMOptions()); - command.add("-Dtest.javac.opts=" + script.getTestCompilerOptions()); - command.add("-Dtest.java.opts=" + script.getTestJavaOptions()); + command.add("-Dtest.vm.opts=" + join(script.getTestVMOptions())); + command.add("-Dtest.tool.vm.opts=" + join(script.getTestToolVMOptions())); + command.add("-Dtest.javac.opts=" + join(script.getTestCompilerOptions())); + command.add("-Dtest.java.opts=" + join(script.getTestJavaOptions())); String newPolicyFN; if (policyFN != null) { @@ -364,7 +364,7 @@ } // runOtherJVM() private static Hashtable savedSystemProperties; - + private Status runSameJVM() throws TestRunException { // TAG-SPEC: "The source and class directories of a test are made // available to main and applet actions via the system properties @@ -376,6 +376,11 @@ Properties p = System.getProperties(); if (savedSystemProperties == null) savedSystemProperties = copyProperties(p); + p.put("java.class.path", + script.absTestClsDir() + PATHSEP + + script.absTestSrcDir() + PATHSEP + + script.absClsLibListStr() + PATHSEP + + p.getProperty("java.class.path")); p.put("test.src", script.absTestSrcDir().getPath()); p.put("test.classes", script.absTestClsDir().getPath()); p.put("test.vm.opts", StringUtils.join(script.getTestVMOptions(), " ")); @@ -390,18 +395,18 @@ //return Status.error(MAIN_SECMGR_BAD); } } - + ByteArrayOutputStream newOut = new ByteArrayOutputStream(); ByteArrayOutputStream newErr = new ByteArrayOutputStream(); PrintStream psOut = new PrintStream(newOut); PrintStream psErr = new PrintStream(newErr); - + Status status; PrintStream saveOut = System.out; PrintStream saveErr = System.err; try { status = Status.passed(EXEC_PASS); - + String[] classpath = StringArray.splitSeparator(PATHSEP, script.testClassPath()); List<URL> urls = new ArrayList<URL>(); for (int i = 0; i < classpath.length; i++) { @@ -417,18 +422,18 @@ Class<?> c = loader.loadClass(buildFN); Class<?>[] argTypes = { String[].class }; Method method = c.getMethod("main", argTypes); - + // XXX 4/1 possible to use splitSeparator instead? String[] tmpArgs = StringArray.splitWS(mainArgs); Object[] runArgs = {tmpArgs}; - + Status stat = redirectOutput(psOut, psErr); if (!stat.isPassed()) { return stat; } - + // RUN JAVA IN ANOTHER THREADGROUP - + SameVMThreadGroup tg = new SameVMThreadGroup(); SameVMThread svmt = new SameVMThread(method, runArgs, psErr); Thread t = new Thread(tg, svmt, "SameVMThread"); @@ -443,7 +448,7 @@ } } tg.cleanup(); - + if (((svmt.t != null) || (tg.uncaughtThrowable != null)) && (error == null)) { if (svmt.t == null) error = tg.uncaughtThrowable; @@ -451,12 +456,12 @@ error = svmt.t; status = Status.failed(MAIN_THREW_EXCEPT + error.toString()); } - + // EVALUATE RESULTS if (status.getReason().endsWith("java.lang.SecurityException: System.exit() forbidden by JavaTest")) { status = Status.failed(UNEXPECT_SYS_EXIT); } else { - + boolean ok = status.isPassed(); int st = status.getType(); String sr; @@ -503,19 +508,20 @@ System.setProperties(newProperties(savedSystemProperties)); // System.err.println("reset properties"); } else { + System.setProperty("java.class.path", (String) savedSystemProperties.get("java.class.path")); // System.err.println("no need to reset properties"); } rsm.setAllowPropertiesAccess(false); } - + Status stat = redirectOutput(saveOut, saveErr); if (!stat.isPassed()) { return stat; } - + psOut.close(); psErr.close(); - + String outString = newOut.toString(); String errString = newErr.toString(); PrintWriter sysOut = section.createOutput("System.out"); @@ -528,7 +534,7 @@ if (sysErr != null) sysErr.close(); } } - + return status; } // runSameJVM() @@ -539,7 +545,7 @@ value = "novalue"; return value; } // parseMainManual() - + private static Hashtable<Object,Object> copyProperties(Properties p) { Hashtable<Object,Object> h = new Hashtable<Object,Object>(); for (Enumeration<?> e = p.propertyNames(); e.hasMoreElements(); ) { @@ -548,7 +554,7 @@ } return h; } - + private static Properties newProperties(Hashtable<?,?> h) { Properties p = new Properties(); for (Enumeration<?> e = h.keys(); e.hasMoreElements(); ) { @@ -556,7 +562,17 @@ p.put(key, h.get(key)); } return p; - + + } + + private String join(List<String> list) { + StringBuffer sb = new StringBuffer(); + for (String s: list) { + if (sb.length() > 0) + sb.append(" "); + sb.append(s); + } + return sb.toString(); } //----------internal classes------------------------------------------------ @@ -630,27 +646,27 @@ private void cleanup() { cleanMode = true; - + final int CLEANUP_ROUNDS = 4; final long MAX_CLEANUP_TIME_MILLIS = 2 * 60 * 1000; final long CLEANUP_MILLIS_PER_ROUND = MAX_CLEANUP_TIME_MILLIS / CLEANUP_ROUNDS; final long NANOS_PER_MILLI = 1000L * 1000L; - + long startCleanupTime = System.nanoTime(); - + for (int i = 1; i <= CLEANUP_ROUNDS; i++) { long deadline = startCleanupTime + i * CLEANUP_MILLIS_PER_ROUND * NANOS_PER_MILLI; List<Thread> liveThreads = liveThreads(); - if (liveThreads.isEmpty()) { + if (liveThreads.isEmpty()) { // nothing left to cleanup cleanupOK = true; return; } - + // kick the remaining live threads for (Thread thread : liveThreads) thread.interrupt(); - + // try joining as many threads as possible before // the round times out for (Thread thread : liveThreads) { @@ -663,10 +679,10 @@ } } } - + cleanupOK = liveThreads().isEmpty(); } // cleanup() - + /** * Gets all the "interesting" threads in the thread group. * @see ThreadGroup#enumerate(Thread[])
--- a/test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/regtest/RegressionSecurityManager.java Sun Nov 09 22:29:59 2008 +0100 @@ -25,7 +25,6 @@ package com.sun.javatest.regtest; -import java.lang.RuntimePermission; import java.security.Permission; import java.util.PropertyPermission; @@ -55,7 +54,7 @@ System.err.println("execution of sameJVM tests"); System.err.println(); } - else + else System.setSecurityManager(new RegressionSecurityManager()); } catch (SecurityException e) { @@ -104,13 +103,13 @@ // allow most stuff, but limit as appropriate if (perm instanceof RuntimePermission) { if (perm.getName().equals("setIO")) { - if (!allowSetIO) + if (!allowSetIO) // is this right or should we really restrict this more? super.checkPermission(new java.lang.RuntimePermission("setIO")); } else if (perm.getName().equals("exitVM")) checkExit(0); - else if (perm.getName().equals("createSecurityManager")) + else if (perm.getName().equals("createSecurityManager")) super.checkPermission(new java.lang.RuntimePermission("createSecurityManager")); } else if (perm instanceof PropertyPermission) { @@ -118,21 +117,21 @@ checkPropertiesAccess(); } } - + private boolean propertiesAccessed; - + public synchronized void checkPropertiesAccess() { super.checkPropertiesAccess(); propertiesAccessed = true; } - + boolean isPropertiesAccessed() { return propertiesAccessed; } - + void resetPropertiesAccessed() { propertiesAccessed = false; - } + } public boolean setAllowSetIO(boolean bool) { boolean prev = allowSetIO;
--- a/test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/regtest/RegressionTestFinder.java Sun Nov 09 22:29:59 2008 +0100 @@ -40,6 +40,7 @@ import com.sun.javatest.finder.TagTestFinder; import com.sun.javatest.finder.HTMLCommentStream; import com.sun.javatest.finder.ShScriptCommentStream; +import java.util.regex.Pattern; /** * This is a specific implementation of the TagTestFinder which is to be used @@ -169,36 +170,33 @@ } // force more key words based on actions - String name; String value = newTagValues.get("run"); String origKeywords = newTagValues.get("keywords"); String addKeywords = ""; - if (value.indexOf(name = "othervm") != -1) - addKeywords += "othervm "; + if (match(value, OTHERVM_OPTION)) + addKeywords += " othervm"; - if (value.indexOf(name = "manual") != -1) - addKeywords += "manual "; + if (match(value, MANUAL_OPTION)) + addKeywords += " manual"; - if (value.indexOf(name = "shell") != -1) - addKeywords += "shell "; + if (match(value, SHELL_ACTION)) + addKeywords += " shell"; - if (value.indexOf(name = "ignore") != -1) - addKeywords += "ignore "; + if (match(value, IGNORE_ACTION)) + addKeywords += " ignore"; if (!addKeywords.equals("")) { if (origKeywords == null) newTagValues.put("keywords", addKeywords.trim()); else - newTagValues.put("keywords", origKeywords + " " + addKeywords.trim()); + newTagValues.put("keywords", origKeywords + addKeywords); } /* - for (Enumeration e = newTagValues.keys(); e.hasMoreElements(); ) { - name = (String) e.nextElement(); - value = (String) newTagValues.get(name); - System.out.println("NAME: " + name + " VALUE: " + value); + for (Map.Entry<String,String> e: newTagValues.entrySet()) { + System.out.println("NAME: " + e.getKey() + " VALUE: " + e.getValue()); // if (name.equals("keywords")) // System.out.println(currFile + " " + "`" + value + "'"); } @@ -206,6 +204,10 @@ return newTagValues; } + + private static boolean match(CharSequence cs, Pattern p) { + return p.matcher(cs).matches(); + } /** * Make sure that the provide name-value pair is of the proper format as @@ -221,7 +223,6 @@ { Map<String,String> tagValues = (Map<String,String>) tv; - File currFile = getCurrentFile(); // check for valid tag name, don't produce error message for the // the SCCS sequence '%' 'W' '%' if (name.startsWith("(#)")) @@ -552,6 +553,12 @@ private static final boolean allowLocalKeys = Boolean.parseBoolean(System.getProperty("javatest.regtest.allowLocalKeys", "true")); + + private static final Pattern + OTHERVM_OPTION = Pattern.compile(".*/othervm[/ \t].*", Pattern.DOTALL), + MANUAL_OPTION = Pattern.compile(".*/manual[/= \t].*", Pattern.DOTALL), + SHELL_ACTION = Pattern.compile(".*[ \t]shell[/ \t].*", Pattern.DOTALL), + IGNORE_ACTION = Pattern.compile(".*[ \t]ignore[/ \t].*", Pattern.DOTALL); //----------member variables------------------------------------------------
--- a/test/jtreg/com/sun/javatest/regtest/i18n.properties Sun Nov 09 22:27:11 2008 +0100 +++ b/test/jtreg/com/sun/javatest/regtest/i18n.properties Sun Nov 09 22:29:59 2008 +0100 @@ -176,6 +176,7 @@ re-run any tests. A work directory containing the results of the executed \ tests must be provided. The default location is "./JTwork". To specify an \ alternate directory, use -workDir. +help.main.nr.desc=Do not generate a final report. help.main.startHttpd.desc=Start the http server to view test results help.main.timeout.desc=A scaling factor to extend the default timeout of all \ tests. Typically used when running on slow file systems.