1
2 package org.freehep.graphicsio.test;
3
4 import java.io.File;
5 import java.io.FileWriter;
6 import java.io.IOException;
7 import java.io.PrintWriter;
8 import java.lang.reflect.Array;
9 import java.lang.reflect.Constructor;
10 import java.lang.reflect.Method;
11 import java.util.ArrayList;
12 import java.util.Date;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Properties;
16 import java.util.SortedMap;
17 import java.util.StringTokenizer;
18 import java.util.TreeMap;
19
20 import junit.framework.AssertionFailedError;
21
22 import org.freehep.graphicsio.ImageGraphics2D;
23 import org.freehep.graphicsio.ImageConstants;
24 import org.freehep.util.export.ExportFileType;
25 import org.freehep.util.io.UniquePrintStream;
26
27
28
29
30
31 public class TestSuite extends junit.framework.TestSuite {
32
33 class Format {
34 private String name;
35 private String lowerCaseName;
36 private String upperCaseName;
37 private String extension;
38 private String moduleName;
39 private boolean enabled;
40 private boolean bitmap;
41 private int jiraId;
42 private String testDir;
43
44 public Format(String name, String extension, String moduleName,
45 boolean enabled, boolean bitmap, int jiraId, String testDir) {
46 this.name = name;
47 this.lowerCaseName = name.toLowerCase();
48 this.upperCaseName = name.toUpperCase();
49 this.extension = extension;
50 this.moduleName = moduleName;
51 this.enabled = enabled;
52 this.bitmap = bitmap;
53 this.jiraId = jiraId;
54 this.testDir = testDir;
55 }
56
57 public String getName() {
58 return name;
59 }
60
61 public String getLowerCaseName() {
62 return lowerCaseName;
63 }
64
65 public String getUpperCaseName() {
66 return upperCaseName;
67 }
68
69 public String getExtension() {
70 return extension != null ? extension : lowerCaseName;
71 }
72
73 public String getModuleName() {
74 return moduleName != null ? moduleName : "freehep-graphicsio-"
75 + lowerCaseName;
76 }
77
78 public boolean isEnabled() {
79 return enabled;
80 }
81
82 public boolean isBitmap() {
83 return bitmap;
84 }
85
86 public int getJiraId() {
87 return jiraId;
88 }
89
90 public String getTestDir() {
91 return testDir != null ? testDir : lowerCaseName;
92 }
93 }
94
95 private SortedMap bitmapFormats, vectorFormats;
96 private static final String jiraURL = "http://bugs.freehep.org/secure/IssueNavigator.jspa?reset=true&mode=hide&sorter/order=DESC&sorter/field=priority&resolutionIds=-1";
97 private static final int jiraProductId = 10170;
98
99 class Test {
100 private String name;
101 private boolean enabled;
102
103 public Test(String name, boolean enabled) {
104 this.name = name;
105 this.enabled = enabled;
106 }
107
108 public String getName() {
109 return name;
110 }
111
112 public boolean isEnabled() {
113 return enabled;
114 }
115 }
116
117 private List tests;
118
119 private static final String gioPackage = "org.freehep.graphicsio.";
120 private static final String testPackage = gioPackage + "test.";
121 private static final String testDir = "target/site/test-output/";
122 private String testOutDir;
123 private String os;
124 private String jdk;
125
126 private boolean local = true;
127
128 public static class TestCase extends junit.framework.TestCase {
129
130 private String name, fullName, pkg, testOutDir;
131
132 private Format fmt;
133
134 private Properties properties;
135
136 public TestCase(String name, Format fmt, String testOutDir,
137 Properties properties) {
138 super("GraphicsIO Test for " + testPackage + name + " in "
139 + fmt.getName());
140 this.fullName = testPackage + name;
141 int dot = fullName.lastIndexOf(".");
142 this.name = dot < 0 ? fullName : fullName.substring(dot + 1);
143 this.fmt = fmt;
144 this.pkg = "org.freehep.graphicsio." + fmt.getLowerCaseName();
145 this.testOutDir = testOutDir;
146 this.properties = properties;
147 }
148
149 protected void runTest() throws Throwable {
150 String base = "src/test/resources/";
151
152 String baseDir = System.getProperty("basedir");
153 if (baseDir != null)
154 base = baseDir + "/" + base;
155
156 String out = testOutDir + fmt.getTestDir() + "/";
157 if (baseDir != null)
158 out = baseDir + "/" + out;
159 (new File(out)).mkdirs();
160
161 Class cls = Class.forName(fullName);
162 String targetName = out + name + "." + fmt.getExtension();
163
164 Object args;
165 if (fmt.isBitmap()) {
166 args = Array.newInstance(String.class, 3);
167 Array.set(args, 0, ImageGraphics2D.class.getName());
168 Array.set(args, 1, fmt.getLowerCaseName());
169 Array.set(args, 2, targetName);
170 } else {
171 args = Array.newInstance(String.class, 2);
172 Array.set(args, 0, pkg + "." + fmt.getName() + "Graphics2D");
173 Array.set(args, 1, targetName);
174 }
175
176
177 Constructor constructor = cls.getConstructor(new Class[] { args
178 .getClass() });
179 Object test = constructor.newInstance(new Object[] { args });
180
181
182 Method runTest = test.getClass().getMethod("runTest",
183 new Class[] { Properties.class });
184 runTest.invoke(test, new Object[] { properties });
185
186 return;
187 }
188 }
189
190 protected TestSuite() {
191 super("GraphicsIO Test Suite");
192
193 local = !System.getProperty("vg.local", "true").equals("false");
194
195 bitmapFormats = new TreeMap();
196 bitmapFormats.put(
197 ImageConstants.BMP.toLowerCase(),
198 new Format(ImageConstants.BMP, null, "freehep-graphicsio-tests", true, true, 10241, null));
199 bitmapFormats.put(
200 ImageConstants.GIF.toLowerCase(),
201 new Format(ImageConstants.GIF, null, "freehep-graphicsio-tests", true, true, 10241, null));
202 bitmapFormats.put(
203 ImageConstants.JPG.toLowerCase(),
204 new Format(ImageConstants.JPG, null, "freehep-graphicsio-tests", true, true, 10241, null));
205 bitmapFormats.put(
206 ImageConstants.PNG.toLowerCase(),
207 new Format(ImageConstants.PNG, null, "freehep-graphicsio-tests", true, true, 10241, null));
208 bitmapFormats.put(
209 ImageConstants.WBMP.toLowerCase(),
210 new Format(ImageConstants.WBMP, null, "freehep-graphicsio-tests", true, true, 10241, null));
211
212 vectorFormats = new TreeMap();
213
214
215 vectorFormats.put(
216 ImageConstants.EMF.toLowerCase(),
217 new Format(ImageConstants.EMF, null, null, true, false, 10231, null));
218 vectorFormats.put(
219 ImageConstants.JAVA.toLowerCase(),
220 new Format(ImageConstants.JAVA, null, null, false, false,
221 10238, "org/freehep/graphicsio/java/test"));
222
223
224 vectorFormats.put(
225 ImageConstants.PDF.toLowerCase(),
226 new Format("PDF", null, null, true, false, 10235, null));
227 vectorFormats.put(
228 ImageConstants.PS.toLowerCase(),
229 new Format(ImageConstants.PS, null, null, true, false, 10232, null));
230 vectorFormats.put(
231 ImageConstants.SVG.toLowerCase(),
232 new Format(ImageConstants.SVG, null, null, true, false, 10236, null));
233 vectorFormats.put(
234 ImageConstants.SWF.toLowerCase(),
235 new Format(ImageConstants.SWF, null, null, true, false, 10237, null));
236
237 boolean on = true;
238
239 boolean onMacOSXandJDK15 = System.getProperty("os.name").equals(
240 "Mac OS X")
241 && System.getProperty("java.version").startsWith("1.5");
242
243
244 tests = new ArrayList();
245 tests.add(new Test("TestAll", on));
246 tests.add(new Test("TestClip", on));
247 tests.add(new Test("TestColors", on));
248 tests.add(new Test("TestCustomStrokes", on));
249 tests.add(new Test("TestFonts", on));
250 tests.add(new Test("TestFontDerivation", on));
251 tests.add(new Test("TestGraphicsContexts", on));
252 tests.add(new Test("TestHistogram", on));
253 tests.add(new Test("TestHTML", on));
254 tests.add(new Test("TestImages", on));
255 tests.add(new Test("TestImage2D", on));
256 tests.add(new Test("TestLabels", on));
257 tests.add(new Test("TestLineStyles", on));
258 tests.add(new Test("TestOffset", on));
259 tests.add(new Test("TestPaint", on));
260 tests.add(new Test("TestPrintColors", on));
261 tests.add(new Test("TestRenderingHints", on));
262 tests.add(new Test("TestResolution", on));
263 tests.add(new Test("TestScatterPlot", on));
264 tests.add(new Test("TestShapes", on));
265 tests.add(new Test("TestSymbols2D", on));
266 tests.add(new Test("TestTaggedString", on));
267 tests.add(new Test("TestText2D", on));
268 tests.add(new Test("TestTransforms", on));
269 tests.add(new Test("TestTransparency", on));
270
271 os = System.getProperty("os.name", "OS");
272 if (os.equals("Mac OS X")) {
273 os = "MacOSX";
274 } else if (os.startsWith("Windows")) {
275 os = "Windows";
276 }
277 jdk = System.getProperty("java.version", "0.0");
278 int dot;
279 if ((dot = jdk.indexOf('.')) > 0) {
280 if ((dot = jdk.indexOf('.', dot + 1)) > 0) {
281 jdk = jdk.substring(0, dot);
282 }
283 }
284 jdk = "JDK-" + jdk;
285 testOutDir = testDir + os + "/" + jdk + "/";
286 }
287
288 protected void addTests(Format fmt, Properties properties) {
289 if ((fmt == null) || !fmt.isEnabled())
290 return;
291
292 for (Iterator i = tests.iterator(); i.hasNext();) {
293 Test test = (Test) i.next();
294 if (test.isEnabled()) {
295 addTest(new TestCase(test.getName(), fmt, testOutDir,
296 properties));
297 writeHTML(test, fmt, os, jdk);
298 } else {
299 System.err.println("NOTE: " + test.getName() + " disabled for "+fmt.getName()+".");
300 }
301 }
302 }
303
304 protected void addTests(String formatName, Properties properties) {
305 Format fmt = (Format) bitmapFormats.get(formatName.toLowerCase());
306 if (fmt == null) {
307 fmt = (Format) vectorFormats.get(formatName.toLowerCase());
308 }
309 addTests(fmt, properties);
310 }
311
312 protected void addTests(String formatName) {
313 addTests(formatName, null);
314 }
315
316 protected void addTests(String[] args) {
317 if (args.length > 0) {
318 for (int i = 0; i < args.length; i++) {
319 addTests(args[i]);
320 }
321 } else {
322 for (Iterator i = bitmapFormats.keySet().iterator(); i.hasNext();) {
323 Format fmt = (Format) bitmapFormats.get((String) i.next());
324 addTests(fmt, null);
325 }
326 for (Iterator i = vectorFormats.keySet().iterator(); i.hasNext();) {
327 Format fmt = (Format) vectorFormats.get((String) i.next());
328
329 addTests(fmt, null);
330 }
331 }
332 }
333
334 private void writeHTML(Test test, Format fmt, String os, String jdk) {
335
336 String site = "../../../../";
337 String css = site + "css";
338
339 String top = site + (local ? "../../" : "") + "../";
340 String refFormat = ImageConstants.PNG.toLowerCase();
341
342 String testSite = top + "freehep-graphicsio-tests/"
343 + (local ? "target/site/" : "");
344 String ref = testSite + "ref-output/" + refFormat + "/";
345 String cloud = testSite + "images/" + "cloudy.jpg";
346
347 String title = (local ? "[LOCAL] " : "") + "VectorGraphics " + fmt.getName()
348 + " " + test.getName();
349 String freehep = "http://java.freehep.org/";
350 String freehepImage = freehep + "images/sm-freehep.gif";
351 String url = freehep + "vectorgraphics/freehep-graphicsio-" + fmt.getLowerCaseName();
352
353 String out = testOutDir + fmt.getTestDir() + "/";
354 String baseDir = System.getProperty("basedir");
355 if (baseDir != null)
356 out = baseDir + "/" + out;
357 try {
358
359
360
361
362 ExportFileType.setClassLoader(getClass().getClassLoader());
363 List fileTypes = ExportFileType.getExportFileTypes(fmt.getLowerCaseName());
364 if (fileTypes.size() <= 0) throw new AssertionFailedError("No ExportFileType found for format '"+fmt.getLowerCaseName()+"'");
365 String[] mimeTypes = ((ExportFileType)fileTypes.get(0)).getMIMETypes();
366 if (mimeTypes.length <= 0) throw new AssertionFailedError("No MimeTypes found for ExportFileType '"+fmt.getLowerCaseName()+"'");
367
368 (new File(out)).mkdirs();
369 PrintWriter w = new PrintWriter(new FileWriter(out + test.getName()
370 + ".html"));
371
372 w
373 .println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
374 w.println("<html>");
375 w.println(" <head>");
376 w.println(" <title>" + title + "</title>");
377 w.println(" <style type=\"text/css\" media=\"all\">");
378 w.println(" @import url(\"" + css + "/maven-base.css\");");
379 w
380 .println(" @import url(\"" + css
381 + "/maven-theme.css\");");
382 w.println(" @import url(\"" + css + "/site.css\");");
383 w.println(" </style>");
384 w.println(" <link rel=\"stylesheet\" href=\"" + css
385 + "/print.css\" type=\"text/css\" media=\"print\" />");
386 w
387 .println(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\" />");
388 w.println(" </head>");
389 w.println(" <body class=\"composite\">");
390 w.println(" <div id=\"banner\">");
391 w.println(" <a href=\"" + url + "\" id=\"bannerLeft\">");
392 w.println(" " + (local ? "[LOCAL] " : "")
393 + "FreeHEP VectorGraphics Test " + fmt.getName());
394 w.println(" </a>");
395 w.println(" <a href=\"" + freehep
396 + "\" id=\"bannerRight\">");
397 w.println(" <img src=\"" + freehepImage
398 + "\" alt=\"\" />");
399 w.println(" </a>");
400 w.println(" <div class=\"clear\">");
401 w.println(" <hr/>");
402 w.println(" </div>");
403 w.println(" </div>");
404 w.println(" <div id=\"breadcrumbs\">");
405 w.println(" <div class=\"xleft\">Last Run: "
406 + (new Date()) + "</div>");
407 w.println(" <div class=\"xright\"><a href=\"" + freehep
408 + "\">FreeHEP</a>");
409 w.println(" |");
410 w
411 .println(" <a href=\"http://jas.freehep.org/\">JAS</a>");
412 w.println(" |");
413 w
414 .println(" <a href=\"http://wired.freehep.org/\">WIRED</a>");
415 w.println(" </div>");
416 w.println(" <div class=\"clear\">");
417 w.println(" <hr/>");
418 w.println(" </div>");
419 w.println(" </div>");
420 w.println(" <div id=\"leftColumn\">");
421 w.println(" <div id=\"navcolumn\">");
422
423 if (!local) {
424 w.println(" <h5><a href=\"" + top
425 + "index.html" + "\">Back</a></h5>");
426 }
427
428 w.println(" <h5>Operating System</h5>");
429 w.println(" <ul>");
430
431 String[] oss = { "Windows", "Linux", "MacOSX" };
432 for (int i = 0; i < oss.length; i++) {
433 if (!local || os.equals(oss[i])) {
434 w.println(" <li class=\"none\">");
435 if (os.equals(oss[i]))
436 w.println(" <strong>");
437 w.println(" <a href=\"" + top
438 + fmt.getModuleName() + "/"
439 + (local ? "target/site/" : "") + "test-output/" + oss[i] + "/" + jdk
440 + "/" + fmt.getLowerCaseName() + "/"
441 + test.getName() + ".html\">" + oss[i] + "</a>");
442 if (os.equals(oss[i]))
443 w.println(" </strong>");
444 w.println(" </li>");
445 }
446 }
447 w.println(" </ul>");
448
449 w.println(" <h5>Java</h5>");
450 w.println(" <ul>");
451
452 w.println(" <li class=\"none\">");
453 String[] jdks = { "JDK-1.5", "JDK-1.6" };
454 for (int i=0; i<jdks.length; i++) {
455 if (!local || jdk.equals(jdks[i])) {
456 w.println(" <li class=\"none\">");
457 if (jdk.equals(jdks[i]))
458 w.println(" <strong>");
459 w.println(" <a href=\"" + top
460 + fmt.getModuleName() + "/"
461 + (local ? "target/site/" : "") + "test-output/" + os + "/" + jdks[i] + "/"
462 + fmt.getLowerCaseName() + "/" + test.getName()
463 + ".html\">" + jdks[i] + "</a>");
464 if (jdk.equals(jdks[i]))
465 w.println(" </strong>");
466 w.println(" </li>");
467 }
468
469 }
470 w.println(" </ul>");
471
472 w.println(" <h5>Vector Formats</h5>");
473 w.println(" <ul>");
474 for (Iterator i = vectorFormats.keySet().iterator(); i.hasNext();) {
475 String key = (String) i.next();
476 w.println(" <li class=\"none\">");
477 if (key.equalsIgnoreCase(fmt.getLowerCaseName())) {
478 w.println(" <strong>");
479 }
480 Format value = (Format) vectorFormats.get(key);
481 w.print(" ");
482 if (value.isEnabled()) {
483 w.print("<a href=\"" + top + value.getModuleName() + "/"
484 + (local ? "target/site/" : "") + "test-output/" + os + "/" + jdk
485 + "/" + key + "/" + test.getName() + ".html\">");
486 }
487 w.print(value.getName());
488 if (value.isEnabled()) {
489 w.print("</a>");
490 }
491 w.println();
492 if (key.equalsIgnoreCase(fmt.getLowerCaseName()))
493 w.println(" </strong>");
494 w.println(" </li>");
495 }
496 w.println(" </ul>");
497
498 w.println(" <h5>Bitmap Formats</h5>");
499 w.println(" <ul>");
500 for (Iterator i = bitmapFormats.keySet().iterator(); i.hasNext();) {
501 String key = (String) i.next();
502 w.println(" <li class=\"none\">");
503 if (key.equalsIgnoreCase(fmt.getLowerCaseName())) {
504 w.println(" <strong>");
505 }
506 Format value = (Format) bitmapFormats.get(key);
507 w.print(" ");
508 if (value.isEnabled()) {
509 w.print("<a href=\"" + top + value.getModuleName() + "/"
510 + (local ? "target/site/" : "") + "test-output/" + os + "/" + jdk
511 + "/" + key + "/" + test.getName() + ".html\">");
512 }
513 w.print(value.getName());
514 if (value.isEnabled()) {
515 w.print("</a>");
516 }
517 w.println();
518 if (key.equalsIgnoreCase(fmt.getLowerCaseName()))
519 w.println(" </strong>");
520 w.println(" </li>");
521 }
522 w.println(" </ul>");
523
524 w.println(" <h5>" + fmt.getName() + " Tests</h5>");
525 w.println(" <ul>");
526 for (Iterator i = tests.iterator(); i.hasNext();) {
527 Test t = (Test) i.next();
528 w.println(" <li class=\"none\">");
529 if (t.equals(test))
530 w.println(" <strong>");
531 w.print(" ");
532 if (t.isEnabled()) {
533 w.print("<a href=\"" + t.getName() + ".html\">");
534 }
535 w.print(t.getName());
536 if (t.isEnabled()) {
537 w.print("</a>");
538 }
539 w.println();
540 if (t.equals(test))
541 w.println(" </strong>");
542 w.println(" </li>");
543 }
544 w.println(" </ul>");
545
546 w.println(" <h5>" + fmt.getName() + " Links</h5>");
547 w.println(" <ul>");
548 w.println(" <li><a href=\"" + jiraURL + "&pid="
549 + jiraProductId + "&component=" + fmt.getJiraId()
550 + "\">Issues</a></li>");
551 w.println(" </ul>");
552
553 w.println(" <a href=\"" + freehep
554 + "\" title=\"Built by FreeHEP\" id=\"poweredBy\">");
555 w.println(" <img alt=\"Built by FreeHEP\" src=\""
556 + freehepImage + "\"></img>");
557 w.println(" </a>");
558 w.println(" </div>");
559 w.println(" </div>");
560 w.println(" <div id=\"bodyColumn\">");
561 w.println(" <div id=\"contentBox\">");
562 w.println(" <div class=\"section\">");
563 w.println(" <h2>" + (local ? "[LOCAL] " : "")
564 + test.getName() + " " + fmt.getName() + "</h2>");
565 w.println(" <table class=\"bodyTable\">");
566
567 w.println(" <tr class=\"a\">");
568 w.println(" <th>" + fmt.getName() + "</th>");
569 w.println(" <th>Reference ("
570 + refFormat.toUpperCase() + ")</th>");
571 w.println(" </tr>");
572 w.println(" <tr class=\"a\">");
573 w.println(" <td><a href=\"" + test.getName() + "."
574 + fmt.getExtension() + "\">" + test.getName() + "." + fmt.getExtension() + "</a></td>");
575 w.println(" <td><a href=\"" + ref + test.getName()
576 + "." + refFormat + "\">" + test.getName() + "."
577 + refFormat + "</a></td>");
578 w.println(" </tr>");
579 w.println(" <tr class=\"a\">");
580 Test[] testArray = (Test[]) tests.toArray(new Test[0]);
581 int testIndex = 0;
582 while (testIndex < testArray.length) {
583 if (testArray[testIndex].equals(test))
584 break;
585 testIndex++;
586 }
587 int previousIndex = testIndex - 1;
588 while ((previousIndex >= 0)
589 && !testArray[previousIndex].isEnabled())
590 previousIndex--;
591 if (previousIndex >= 0) {
592 w.println(" <td><a href=\""
593 + testArray[previousIndex].getName()
594 + ".html\">previous</a></td>");
595 } else {
596 w.println(" <td/>");
597 }
598 int nextIndex = testIndex + 1;
599 while ((nextIndex < testArray.length)
600 && !testArray[nextIndex].isEnabled())
601 nextIndex++;
602 if (nextIndex < testArray.length) {
603 w.println(" <td><a href=\""
604 + testArray[nextIndex].getName()
605 + ".html\">next</a></td>");
606 } else {
607 w.println(" <td/>");
608 }
609 w.println(" </tr>");
610 w.println(" <tr class=\"b\">");
611
612
613 w.print(" ");
614 w.print("<td background=\"" + cloud + "\">");
615 w.print("<object type=\"" + mimeTypes[0] + "\" name=\""
616 + test.getName() + "\" data=\"" + test.getName() + "."
617 + fmt.getExtension() + "\" width=\"" + TestingPanel.width + "\" height=\""
618 + TestingPanel.height + "\">");
619 w.print("<param name=\"wmode\" value=\"transparent\"/>");
620 w.print("Image not embeddable: " + mimeTypes[0]);
621 w.print("</object>");
622 w.println("</td>");
623 w.println(" <td background=\"" + cloud
624 + "\"><img src=\"" + ref + test.getName() + "." + refFormat
625 + "\"/></td>");
626 w.println(" </tr>");
627 w.println(" </table>");
628 w.println(" </div>");
629 w.println(" </div>");
630 w.println(" </div>");
631 w.println(" <div class=\"clear\">");
632 w.println(" <hr/>");
633 w.println(" </div>");
634 w.println(" <div id=\"footer\">");
635 w.println(" <div class=\"xright\">©");
636 w.println(" 2000-2007");
637 w.println(" FreeHEP");
638 w.println(" </div>");
639 w.println(" <div class=\"clear\">");
640 w.println(" <hr/>");
641 w.println(" </div>");
642 w.println(" </div>");
643 w.println(" </body>");
644 w.println(" </html>");
645 w.close();
646 } catch (IOException e) {
647 System.err.println("Could not write " + out);
648 }
649 }
650
651 public static TestSuite suite() {
652
653 StringTokenizer st = new StringTokenizer(
654 System.getProperty("args", ""), " ");
655 List argList = new ArrayList();
656 while (st.hasMoreTokens()) {
657 String arg = st.nextToken();
658 System.out.println(arg);
659 argList.add(arg);
660 }
661 String[] args = new String[argList.size()];
662 argList.toArray(args);
663
664 TestSuite suite = new TestSuite();
665 suite.addTests(args);
666 return suite;
667 }
668
669 public static void main(String[] args) {
670 UniquePrintStream stderr = new UniquePrintStream(System.err);
671 System.setErr(stderr);
672 TestSuite suite = new TestSuite();
673 suite.addTests(args);
674 junit.textui.TestRunner.run(suite);
675 stderr.finish();
676 }
677 }