001: /* ***** BEGIN LICENSE BLOCK *****
002: * Version: MPL 1.1/GPL 2.0
003: *
004: * The contents of this file are subject to the Mozilla Public License Version
005: * 1.1 (the "License"); you may not use this file except in compliance with
006: * the License. You may obtain a copy of the License at
007: * http://www.mozilla.org/MPL/
008: *
009: * Software distributed under the License is distributed on an "AS IS" basis,
010: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011: * for the specific language governing rights and limitations under the
012: * License.
013: *
014: * The Original Code is the Java port of jsDriver.pl.
015: *
016: * The Initial Developer of the Original Code is
017: * David P. Caldwell.
018: * Portions created by David P. Caldwell are Copyright (C)
019: * 2007 David P. Caldwell. All Rights Reserved.
020: *
021: *
022: * Contributor(s):
023: * David P. Caldwell <inonit@inonit.com>
024: * Norris Boyd <norrisboyd@gmail.com>
025: *
026: * Alternatively, the contents of this file may be used under the terms of
027: * the GNU General Public License Version 2 or later (the "GPL"), in which
028: * case the provisions of the GPL are applicable instead of those above. If
029: * you wish to allow use of your version of this file only under the terms of
030: * the GPL and not to allow others to use your version of this file under the
031: * MPL, indicate your decision by deleting the provisions above and replacing
032: * them with the notice and other provisions required by the GPL. If you do
033: * not delete the provisions above, a recipient may use your version of this
034: * file under either the MPL or the GPL.
035: *
036: * ***** END LICENSE BLOCK ***** */
037:
038: package org.mozilla.javascript.drivers;
039:
040: import java.io.*;
041: import java.util.*;
042:
043: import org.w3c.dom.*;
044:
045: import org.mozilla.javascript.tools.shell.*;
046:
047: /**
048: * @version $Id: JsDriver.java,v 1.5 2007/10/11 19:44:10 szegedia%freemail.hu Exp $
049: */
050: public class JsDriver {
051: private JsDriver() {
052: }
053:
054: private static String join(String[] list) {
055: String rv = "";
056: for (int i = 0; i < list.length; i++) {
057: rv += list[i];
058: if (i + 1 != list.length) {
059: rv += ",";
060: }
061: }
062: return rv;
063: }
064:
065: private static class Tests {
066: private File testDirectory;
067: private String[] list;
068: private String[] skip;
069:
070: Tests(File testDirectory, String[] list, String[] skip) {
071: this .testDirectory = testDirectory;
072: this .list = getTestList(list);
073: this .skip = getTestList(skip);
074: }
075:
076: private String[] getTestList(String[] tests) {
077: ArrayList list = new ArrayList();
078: for (int i = 0; i < tests.length; i++) {
079: if (tests[i].startsWith("@"))
080: addTestsFromFile(tests[i].substring(1), list);
081: else
082: list.add(tests[i]);
083: }
084: return (String[]) list.toArray(new String[0]);
085: }
086:
087: private void addTestsFromFile(String filename, ArrayList list) {
088: try {
089: Properties props = new Properties();
090: props.load(new FileInputStream(new File(filename)));
091: list.addAll(props.keySet());
092: } catch (IOException e) {
093: throw new RuntimeException("Could not read file '"
094: + filename + "'", e);
095: }
096: }
097:
098: private boolean matches(String[] patterns, String path) {
099: for (int i = 0; i < patterns.length; i++) {
100: if (path.startsWith(patterns[i])) {
101: return true;
102: }
103: }
104: return false;
105: }
106:
107: private boolean matches(String path) {
108: if (list.length == 0)
109: return true;
110: return matches(list, path);
111: }
112:
113: private boolean excluded(String path) {
114: if (skip.length == 0)
115: return false;
116: return matches(skip, path);
117: }
118:
119: private void addFiles(List rv, String prefix, File directory) {
120: File[] files = directory.listFiles();
121: if (files == null)
122: throw new RuntimeException("files null for "
123: + directory);
124: for (int i = 0; i < files.length; i++) {
125: String path = prefix + files[i].getName();
126: if (ShellTest.DIRECTORY_FILTER.accept(files[i])) {
127: addFiles(rv, path + "/", files[i]);
128: } else {
129: boolean isTopLevel = prefix.length() == 0;
130: if (ShellTest.TEST_FILTER.accept(files[i])
131: && matches(path) && !excluded(path)
132: && !isTopLevel) {
133: rv.add(new Script(path, files[i]));
134: }
135: }
136: }
137: }
138:
139: static class Script {
140: private String path;
141: private File file;
142:
143: Script(String path, File file) {
144: this .path = path;
145: this .file = file;
146: }
147:
148: String getPath() {
149: return path;
150: }
151:
152: File getFile() {
153: return file;
154: }
155: }
156:
157: Script[] getFiles() {
158: ArrayList rv = new ArrayList();
159: addFiles(rv, "", testDirectory);
160: return (Script[]) rv.toArray(new Script[0]);
161: }
162: }
163:
164: private static class ConsoleStatus extends ShellTest.Status {
165: private File jsFile;
166:
167: private Arguments.Console console;
168: private boolean trace;
169:
170: private boolean failed;
171:
172: ConsoleStatus(Arguments.Console console, boolean trace) {
173: this .console = console;
174: this .trace = trace;
175: }
176:
177: void running(File jsFile) {
178: try {
179: console
180: .println("Running: "
181: + jsFile.getCanonicalPath());
182: this .jsFile = jsFile;
183: } catch (IOException e) {
184: throw new RuntimeException(e);
185: }
186: }
187:
188: void failed(String s) {
189: console.println("Failed: " + jsFile + ": " + s);
190: failed = true;
191: }
192:
193: void threw(Throwable t) {
194: console.println("Failed: " + jsFile + " with exception.");
195: console.println(ShellTest.getStackTrace(t));
196: failed = true;
197: }
198:
199: void timedOut() {
200: console.println("Failed: " + jsFile + ": timed out.");
201: failed = true;
202: }
203:
204: void exitCodesWere(int expected, int actual) {
205: if (expected != actual) {
206: console.println("Failed: " + jsFile + " expected "
207: + expected + " actual " + actual);
208: failed = true;
209: }
210: }
211:
212: void outputWas(String s) {
213: if (!failed) {
214: console.println("Passed: " + jsFile);
215: if (trace) {
216: console.println(s);
217: }
218: }
219: }
220: }
221:
222: // returns true if node was found, false otherwise
223: private static boolean setContent(Element node, String id,
224: String content) {
225: if (node.getAttribute("id").equals(id)) {
226: node.setTextContent(node.getTextContent() + "\n" + content);
227: return true;
228: } else {
229: NodeList children = node.getChildNodes();
230: for (int i = 0; i < children.getLength(); i++) {
231: if (children.item(i) instanceof Element) {
232: Element e = (Element) children.item(i);
233: boolean rv = setContent(e, id, content);
234: if (rv) {
235: return true;
236: }
237: }
238: }
239: }
240: return false;
241: }
242:
243: private static Element getElementById(Element node, String id) {
244: if (node.getAttribute("id").equals(id)) {
245: return node;
246: } else {
247: NodeList children = node.getChildNodes();
248: for (int i = 0; i < children.getLength(); i++) {
249: if (children.item(i) instanceof Element) {
250: Element rv = getElementById((Element) children
251: .item(i), id);
252: if (rv != null) {
253: return rv;
254: }
255: }
256: }
257: }
258: return null;
259: }
260:
261: private static String newlineLineEndings(String s) {
262: StringBuffer rv = new StringBuffer();
263: for (int i = 0; i < s.length(); i++) {
264: if (s.charAt(i) == '\r') {
265: if (i + 1 < s.length() && s.charAt(i + 1) == '\n') {
266: // just skip \r
267: } else {
268: // Macintosh, substitute \n
269: rv.append('\n');
270: }
271: } else {
272: rv.append(s.charAt(i));
273: }
274: }
275: return rv.toString();
276: }
277:
278: private static class HtmlStatus extends ShellTest.Status {
279: private String testPath;
280: private String bugUrl;
281: private String lxrUrl;
282: private Document html;
283: private Element failureHtml;
284: private boolean failed;
285:
286: private String output;
287:
288: HtmlStatus(String lxrUrl, String bugUrl, String testPath,
289: Document html, Element failureHtml) {
290: this .testPath = testPath;
291: this .bugUrl = bugUrl;
292: this .lxrUrl = lxrUrl;
293: this .html = html;
294: this .failureHtml = failureHtml;
295: }
296:
297: void running(File file) {
298: }
299:
300: void failed(String s) {
301: failed = true;
302: setContent(failureHtml, "failureDetails.reason",
303: "Failure reason: \n" + s);
304: }
305:
306: void exitCodesWere(int expected, int actual) {
307: if (expected != actual) {
308: failed = true;
309: setContent(failureHtml, "failureDetails.reason",
310: "expected exit code " + expected + " but got "
311: + actual);
312: }
313: }
314:
315: void threw(Throwable e) {
316: failed = true;
317: setContent(failureHtml, "failureDetails.reason",
318: "Threw Java exception:\n"
319: + newlineLineEndings(ShellTest
320: .getStackTrace(e)));
321: }
322:
323: void timedOut() {
324: failed = true;
325: setContent(failureHtml, "failureDetails.reason",
326: "Timed out.");
327: }
328:
329: void outputWas(String s) {
330: this .output = s;
331: }
332:
333: private String getLinesStartingWith(String prefix) {
334: BufferedReader r = new BufferedReader(new StringReader(
335: output));
336: String line = null;
337: String rv = "";
338: try {
339: while ((line = r.readLine()) != null) {
340: if (line.startsWith(prefix)) {
341: if (rv.length() > 0) {
342: rv += "\n";
343: }
344: rv += line;
345: }
346: }
347: return rv;
348: } catch (IOException e) {
349: throw new RuntimeException("Can't happen.");
350: }
351: }
352:
353: boolean failed() {
354: return failed;
355: }
356:
357: void finish() {
358: if (failed) {
359: getElementById(failureHtml, "failureDetails.status")
360: .setTextContent(getLinesStartingWith("STATUS:"));
361:
362: String bn = getLinesStartingWith("BUGNUMBER:");
363: Element bnlink = getElementById(failureHtml,
364: "failureDetails.bug.href");
365: if (bn.length() > 0) {
366: String number = bn
367: .substring("BUGNUMBER: ".length());
368: if (!number.equals("none")) {
369: bnlink.setAttribute("href", bugUrl + number);
370: getElementById(bnlink,
371: "failureDetails.bug.number")
372: .setTextContent(number);
373: } else {
374: bnlink.getParentNode().removeChild(bnlink);
375: }
376: } else {
377: bnlink.getParentNode().removeChild(bnlink);
378: }
379:
380: getElementById(failureHtml, "failureDetails.lxr")
381: .setAttribute("href", lxrUrl + testPath);
382: getElementById(failureHtml, "failureDetails.lxr.text")
383: .setTextContent(testPath);
384:
385: getElementById(html.getDocumentElement(),
386: "retestList.text").setTextContent(
387: getElementById(html.getDocumentElement(),
388: "retestList.text").getTextContent()
389: + testPath + "\n");
390:
391: getElementById(html.getDocumentElement(),
392: "failureDetails").appendChild(failureHtml);
393: }
394: }
395: }
396:
397: private static class XmlStatus extends ShellTest.Status {
398: private Element target;
399: private Date start;
400:
401: XmlStatus(String path, Element root) {
402: this .target = root.getOwnerDocument().createElement("test");
403: this .target.setAttribute("path", path);
404: root.appendChild(target);
405: }
406:
407: void running(File file) {
408: this .start = new Date();
409: }
410:
411: private Element createElement(Element parent, String name) {
412: Element rv = parent.getOwnerDocument().createElement(name);
413: parent.appendChild(rv);
414: return rv;
415: }
416:
417: private void finish() {
418: Date end = new Date();
419: long elapsed = end.getTime() - start.getTime();
420: this .target
421: .setAttribute("elapsed", String.valueOf(elapsed));
422: }
423:
424: private void setTextContent(Element e, String content) {
425: e.setTextContent(newlineLineEndings(content));
426: }
427:
428: void exitCodesWere(int expected, int actual) {
429: finish();
430: Element exit = createElement(target, "exit");
431: exit.setAttribute("expected", String.valueOf(expected));
432: exit.setAttribute("actual", String.valueOf(actual));
433: }
434:
435: void timedOut() {
436: finish();
437: createElement(target, "timedOut");
438: }
439:
440: void failed(String s) {
441: finish();
442: Element failed = createElement(target, "failed");
443: setTextContent(failed, s);
444: }
445:
446: void outputWas(String message) {
447: finish();
448: Element output = createElement(target, "output");
449: setTextContent(output, message);
450: }
451:
452: void threw(Throwable t) {
453: finish();
454: Element threw = createElement(target, "threw");
455: setTextContent(threw, ShellTest.getStackTrace(t));
456: }
457: }
458:
459: private static class Results {
460: private ShellContextFactory factory;
461: private Arguments arguments;
462: private File output;
463: private boolean trace;
464:
465: private Document html;
466: private Element failureHtml;
467:
468: private Document xml;
469:
470: private Date start;
471: private int tests;
472: private int failures;
473:
474: Results(ShellContextFactory factory, Arguments arguments,
475: boolean trace) {
476: this .factory = factory;
477: this .arguments = arguments;
478:
479: File output = arguments.getOutputFile();
480: if (output == null) {
481: output = new File("rhino-test-results."
482: + new java.text.SimpleDateFormat(
483: "yyyy.MM.dd.HH.mm.ss")
484: .format(new Date()) + ".html");
485: }
486: this .output = output;
487:
488: this .trace = trace;
489: }
490:
491: private Document parse(InputStream in) {
492: try {
493: javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory
494: .newInstance();
495: factory.setValidating(false);
496: javax.xml.parsers.DocumentBuilder dom = factory
497: .newDocumentBuilder();
498: return dom.parse(in);
499: } catch (Throwable t) {
500: throw new RuntimeException("Parser failure", t);
501: }
502: }
503:
504: private Document getTemplate() {
505: return parse(getClass().getResourceAsStream("results.html"));
506: }
507:
508: private void write(Document template, boolean xml) {
509: try {
510: File output = this .output;
511: javax.xml.transform.TransformerFactory factory = javax.xml.transform.TransformerFactory
512: .newInstance();
513: javax.xml.transform.Transformer xform = factory
514: .newTransformer();
515: if (xml) {
516: xform.setOutputProperty(
517: javax.xml.transform.OutputKeys.METHOD,
518: "xml");
519: xform
520: .setOutputProperty(
521: javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION,
522: "yes");
523: output = new File(output.getCanonicalPath()
524: + ".xml");
525: }
526: xform.transform(new javax.xml.transform.dom.DOMSource(
527: template),
528: new javax.xml.transform.stream.StreamResult(
529: new FileOutputStream(output)));
530: } catch (IOException e) {
531: arguments.getConsole().println(
532: "Could not write results file to " + output
533: + ": ");
534: e.printStackTrace(System.err);
535: } catch (javax.xml.transform.TransformerConfigurationException e) {
536: throw new RuntimeException("Parser failure", e);
537: } catch (javax.xml.transform.TransformerException e) {
538: throw new RuntimeException("Parser failure", e);
539: }
540: }
541:
542: void start() {
543: this .html = getTemplate();
544: this .failureHtml = getElementById(
545: html.getDocumentElement(),
546: "failureDetails.prototype");
547: if (this .failureHtml == null) {
548: try {
549: javax.xml.transform.TransformerFactory
550: .newInstance()
551: .newTransformer()
552: .transform(
553: new javax.xml.transform.dom.DOMSource(
554: html),
555: new javax.xml.transform.stream.StreamResult(
556: System.err));
557: } catch (Throwable t) {
558: throw new RuntimeException(t);
559: }
560: throw new RuntimeException("No");
561: }
562: this .failureHtml.getParentNode().removeChild(
563: this .failureHtml);
564:
565: try {
566: this .xml = javax.xml.parsers.DocumentBuilderFactory
567: .newInstance().newDocumentBuilder()
568: .getDOMImplementation().createDocument(null,
569: "results", null);
570: xml.getDocumentElement().setAttribute("timestamp",
571: String.valueOf(new Date().getTime()));
572: xml.getDocumentElement().setAttribute(
573: "optimization",
574: String
575: .valueOf(arguments
576: .getOptimizationLevel()));
577: xml.getDocumentElement().setAttribute("strict",
578: String.valueOf(arguments.isStrict()));
579: xml.getDocumentElement().setAttribute("timeout",
580: String.valueOf(arguments.getTimeout()));
581: } catch (javax.xml.parsers.ParserConfigurationException e) {
582: throw new RuntimeException(e);
583: }
584:
585: this .start = new Date();
586: }
587:
588: void run(Tests.Script script, ShellTest.Parameters parameters) {
589: String path = script.getPath();
590: File test = script.getFile();
591: ConsoleStatus cStatus = new ConsoleStatus(arguments
592: .getConsole(), trace);
593: HtmlStatus hStatus = new HtmlStatus(arguments.getLxrUrl(),
594: arguments.getBugUrl(), path, html,
595: (Element) failureHtml.cloneNode(true));
596: XmlStatus xStatus = new XmlStatus(path, this .xml
597: .getDocumentElement());
598: ShellTest.Status status = ShellTest.Status
599: .compose(new ShellTest.Status[] { cStatus, hStatus,
600: xStatus });
601: try {
602: ShellTest.run(factory, test, parameters, status);
603: } catch (Exception e) {
604: throw new RuntimeException(e);
605: }
606: tests++;
607: if (hStatus.failed()) {
608: failures++;
609: }
610: hStatus.finish();
611: }
612:
613: private void set(Document document, String id, String value) {
614: getElementById(document.getDocumentElement(), id)
615: .setTextContent(value);
616: }
617:
618: void finish() {
619: Date end = new Date();
620: long elapsedMs = end.getTime() - start.getTime();
621: set(html, "results.testlist", join(arguments.getTestList()));
622: set(html, "results.skiplist", join(arguments.getSkipList()));
623: String pct = new java.text.DecimalFormat("##0.00")
624: .format((double) failures / (double) tests * 100.0);
625: set(html, "results.results", "Tests attempted: " + tests
626: + " Failures: " + failures + " (" + pct + "%)");
627: set(html, "results.platform", "java.home="
628: + System.getProperty("java.home") + "\n"
629: + "java.version="
630: + System.getProperty("java.version") + "\n"
631: + "os.name=" + System.getProperty("os.name"));
632: set(html, "results.classpath", System.getProperty(
633: "java.class.path").replace(File.pathSeparatorChar,
634: ' '));
635: int elapsedSeconds = (int) (elapsedMs / 1000);
636: int elapsedMinutes = elapsedSeconds / 60;
637: elapsedSeconds = elapsedSeconds % 60;
638: String elapsed = "" + elapsedMinutes + " minutes, "
639: + elapsedSeconds + " seconds";
640: set(html, "results.elapsed", elapsed);
641: set(html, "results.time", new java.text.SimpleDateFormat(
642: "MMMM d yyyy h:mm:ss aa")
643: .format(new java.util.Date()));
644: write(html, false);
645: write(xml, true);
646: }
647: }
648:
649: private static class ShellTestParameters extends
650: ShellTest.Parameters {
651: private int timeout;
652:
653: ShellTestParameters(int timeout) {
654: this .timeout = timeout;
655: }
656:
657: int getTimeoutMilliseconds() {
658: return timeout;
659: }
660: }
661:
662: void run(Arguments arguments) throws Throwable {
663: if (arguments.help()) {
664: System.out
665: .println("See mozilla/js/tests/README-jsDriver.html; note that some options are not supported.");
666: System.out
667: .println("Consult the Java source code at testsrc/org/mozilla/javascript/JsDriver.java for details.");
668: System.exit(0);
669: }
670:
671: ShellContextFactory factory = new ShellContextFactory();
672: factory.setOptimizationLevel(arguments.getOptimizationLevel());
673: factory.setStrictMode(arguments.isStrict());
674:
675: File path = arguments.getTestsPath();
676: if (path == null) {
677: path = new File("../tests");
678: }
679: if (!path.exists()) {
680: throw new RuntimeException("JavaScript tests not found at "
681: + path.getCanonicalPath());
682: }
683: Tests tests = new Tests(path, arguments.getTestList(),
684: arguments.getSkipList());
685: Tests.Script[] all = tests.getFiles();
686: arguments.getConsole().println(
687: "Running " + all.length + " tests.");
688:
689: Results results = new Results(factory, arguments, arguments
690: .trace());
691:
692: results.start();
693: for (int i = 0; i < all.length; i++) {
694: results.run(all[i], new ShellTestParameters(arguments
695: .getTimeout()));
696: }
697: results.finish();
698: }
699:
700: public static void main(Arguments arguments) throws Throwable {
701: JsDriver driver = new JsDriver();
702: driver.run(arguments);
703: }
704:
705: private static class Arguments {
706: private ArrayList options = new ArrayList();
707:
708: private Option bugUrl = new Option("b", "bugurl", false, false,
709: "http://bugzilla.mozilla.org/show_bug.cgi?id=");
710: private Option optimizationLevel = new Option("o",
711: "optimization", false, false, "-1");
712: private Option strict = new Option(null, "strict", false, true,
713: null);
714: private Option outputFile = new Option("f", "file", false,
715: false, null);
716: private Option help = new Option("h", "help", false, true, null);
717: private Option logFailuresToConsole = new Option("k",
718: "confail", false, true, null);
719: private Option testList = new Option("l", "list", true, false,
720: null);
721: private Option skipList = new Option("L", "neglist", true,
722: false, null);
723: private Option testsPath = new Option("p", "testpath", false,
724: false, null);
725: private Option trace = new Option("t", "trace", false, true,
726: null);
727: private Option lxrUrl = new Option("u", "lxrurl", false, false,
728: "http://lxr.mozilla.org/mozilla/source/js/tests/");
729: private Option timeout = new Option(null, "timeout", false,
730: false, "60000");
731:
732: public static class Console {
733: public void print(String message) {
734: System.out.print(message);
735: }
736:
737: public void println(String message) {
738: System.out.println(message);
739: }
740: }
741:
742: private Console console = new Console();
743:
744: private class Option {
745: private String letterOption;
746: private String wordOption;
747: private boolean array;
748: private boolean flag;
749: private boolean ignored;
750:
751: private ArrayList values = new ArrayList();
752:
753: // array: can this option have multiple values?
754: // flag: is this option a simple true/false switch?
755: Option(String letterOption, String wordOption,
756: boolean array, boolean flag, String unspecified) {
757: this .letterOption = letterOption;
758: this .wordOption = wordOption;
759: this .flag = flag;
760: this .array = array;
761: if (!flag && !array) {
762: this .values.add(unspecified);
763: }
764: options.add(this );
765: }
766:
767: Option ignored() {
768: this .ignored = true;
769: return this ;
770: }
771:
772: int getInt() {
773: return Integer.parseInt(getValue());
774: }
775:
776: String getValue() {
777: return (String) values.get(0);
778: }
779:
780: boolean getSwitch() {
781: return values.size() > 0;
782: }
783:
784: File getFile() {
785: if (getValue() == null)
786: return null;
787: return new File(getValue());
788: }
789:
790: String[] getValues() {
791: return (String[]) values.toArray(new String[0]);
792: }
793:
794: void process(List arguments) {
795: String option = (String) arguments.get(0);
796: String dashLetter = (letterOption == null) ? (String) null
797: : "-" + letterOption;
798: if (option.equals(dashLetter)
799: || option.equals("--" + wordOption)) {
800: arguments.remove(0);
801: if (flag) {
802: values.add(0, (String) null);
803: } else if (array) {
804: while (arguments.size() > 0
805: && !((String) arguments.get(0))
806: .startsWith("-")) {
807: values.add(arguments.remove(0));
808: }
809: } else {
810: values.set(0, arguments.remove(0));
811: }
812: if (ignored) {
813: System.err
814: .println("WARNING: "
815: + option
816: + " is ignored in the Java version of the test driver.");
817: }
818: }
819: }
820: }
821:
822: // -b URL, --bugurl=URL
823: public String getBugUrl() {
824: return bugUrl.getValue();
825: }
826:
827: // -c PATH, --classpath=PATH
828: // Does not apply; we will use the VM's classpath
829:
830: // -e TYPE ..., --engine=TYPE ...
831: // Does not apply; was used to select between SpiderMonkey and Rhino
832:
833: // Not in jsDriver.pl
834: public int getOptimizationLevel() {
835: return optimizationLevel.getInt();
836: }
837:
838: // --strict
839: public boolean isStrict() {
840: return strict.getSwitch();
841: }
842:
843: // -f FILE, --file=FILE
844: public File getOutputFile() {
845: return outputFile.getFile();
846: }
847:
848: // -h, --help
849: public boolean help() {
850: return help.getSwitch();
851: }
852:
853: // -j PATH, --javapath=PATH
854: // Does not apply; we will use this JVM
855:
856: // -k, --confail
857: // TODO Currently this is ignored; not clear precisely what it means (perhaps we should not be logging ordinary
858: // pass/fail to the console currently?)
859: public boolean logFailuresToConsole() {
860: return logFailuresToConsole.getSwitch();
861: }
862:
863: // -l FILE,... or --list=FILE,...
864: public String[] getTestList() {
865: return testList.getValues();
866: }
867:
868: // -L FILE,... or --neglist=FILE,...
869: public String[] getSkipList() {
870: return skipList.getValues();
871: }
872:
873: // -p PATH, --testpath=PATH
874: public File getTestsPath() {
875: return testsPath.getFile();
876: }
877:
878: // -s PATH, --shellpath=PATH
879: // Does not apply; we will use the Rhino shell with any classes given on the classpath
880:
881: // -t, --trace
882: public boolean trace() {
883: return trace.getSwitch();
884: }
885:
886: // -u URL, --lxrurl=URL
887: public String getLxrUrl() {
888: return lxrUrl.getValue();
889: }
890:
891: //
892: // New arguments
893: //
894:
895: // --timeout
896: // Milliseconds to wait for each test
897: public int getTimeout() {
898: return timeout.getInt();
899: }
900:
901: public Console getConsole() {
902: return console;
903: }
904:
905: void process(List arguments) {
906: while (arguments.size() > 0) {
907: String option = (String) arguments.get(0);
908: if (option.startsWith("--")) {
909: // preprocess --name=value options into --name value
910: if (option.indexOf("=") != -1) {
911: arguments.set(0, option.substring(option
912: .indexOf("=")));
913: arguments.add(1, option.substring(option
914: .indexOf("=") + 1));
915: }
916: } else if (option.startsWith("-")) {
917: // could be multiple single-letter options, e.g. -kht, so preprocess them into -k -h -t
918: if (option.length() > 2) {
919: for (int i = 2; i < option.length(); i++) {
920: arguments.add(1, "-"
921: + option.substring(i, i + 1));
922: }
923: arguments.set(0, option.substring(0, 2));
924: }
925: }
926: int lengthBefore = arguments.size();
927: for (int i = 0; i < options.size(); i++) {
928: if (arguments.size() > 0) {
929: ((Option) options.get(i)).process(arguments);
930: }
931: }
932:
933: if (arguments.size() == lengthBefore) {
934: System.err
935: .println("WARNING: ignoring unrecognized option "
936: + arguments.remove(0));
937: }
938: }
939: }
940: }
941:
942: public static void main(String[] args) throws Throwable {
943: ArrayList arguments = new ArrayList();
944: arguments.addAll(Arrays.asList(args));
945: Arguments clArguments = new Arguments();
946: clArguments.process(arguments);
947: main(clArguments);
948: }
949: }
|