1 /*
   2  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  *
   8  *   - Redistributions of source code must retain the above copyright
   9  *     notice, this list of conditions and the following disclaimer.
  10  *
  11  *   - Redistributions in binary form must reproduce the above copyright
  12  *     notice, this list of conditions and the following disclaimer in the
  13  *     documentation and/or other materials provided with the distribution.
  14  *
  15  *   - Neither the name of Oracle nor the names of its
  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * This source code is provided to illustrate the usage of a given feature
  34  * or technique and has been deliberately simplified. Additional steps
  35  * required for a production-quality application, such as security checks,
  36  * input validation and proper error handling, might not be present in
  37  * this sample code.
  38  */
  39 
  40 
  41 package j2dbench;
  42 
  43 import java.io.PrintWriter;
  44 import java.io.FileReader;
  45 import java.io.FileWriter;
  46 import java.io.LineNumberReader;
  47 import java.io.FileNotFoundException;
  48 import java.io.IOException;
  49 import java.io.File;
  50 import java.awt.Frame;
  51 import java.awt.Dimension;
  52 import java.awt.BorderLayout;
  53 import java.awt.event.ActionListener;
  54 import java.awt.event.ActionEvent;
  55 import java.awt.event.WindowAdapter;
  56 import java.awt.event.WindowEvent;
  57 import javax.swing.JFrame;
  58 import javax.swing.JButton;
  59 import javax.swing.JPanel;
  60 import javax.swing.BoxLayout;
  61 import javax.swing.JFileChooser;
  62 import javax.swing.JOptionPane;
  63 import java.text.SimpleDateFormat;
  64 import java.util.Date;
  65 
  66 import j2dbench.tests.GraphicsTests;
  67 import j2dbench.tests.ImageTests;
  68 import j2dbench.tests.MiscTests;
  69 import j2dbench.tests.RenderTests;
  70 import j2dbench.tests.PixelTests;
  71 import j2dbench.tests.iio.IIOTests;
  72 import j2dbench.tests.text.TextConstructionTests;
  73 import j2dbench.tests.text.TextMeasureTests;
  74 import j2dbench.tests.text.TextRenderTests;
  75 import j2dbench.tests.text.TextTests;
  76 
  77 public class J2DBench {
  78     static Group progoptroot;
  79 
  80     static Option.Enable verbose;
  81     static Option.Enable printresults;
  82 
  83     static boolean looping = false;
  84 
  85     static JFrame guiFrame;
  86 
  87     static final SimpleDateFormat sdf =
  88         new SimpleDateFormat("MM.dd.yyyy 'at' HH:mm aaa z");
  89 
  90     public static void init() {
  91         progoptroot = new Group("prog", "Program Options");
  92         progoptroot.setHidden();
  93 
  94         verbose =
  95             new Option.Enable(progoptroot,
  96                               "verbose", "Verbose print statements",
  97                               false);
  98         printresults =
  99             new Option.Enable(progoptroot,
 100                               "printresults", "Print results after each run",
 101                               true);
 102     }
 103 
 104     public static void usage(int exitcode) {
 105         System.out.println("usage: java -jar J2DBench.jar "+
 106                            "[<optionname>=<value>]");
 107         System.out.println("    "+
 108                            "[-list] "+
 109                            "[-gui | -interactive] "+
 110                            "[-batch] "+
 111                            "[-noshow] "+
 112                            "[-nosave] "+
 113                            "[-report:[NMKAUOsmuna/]] "+
 114                            "[-usage | -help] "+
 115                            "\n    "+
 116                            "\n    "+
 117                            "[-loadopts | -loadoptions] <optfile> "+
 118                            "[-saveopts | -saveoptions] <optfile> "+
 119                            "\n    "+
 120                            "[-saveres | -saveresults] <resfile> "+
 121                            "[-appres | -appendresults] <resfile> "+
 122                            "\n    "+
 123                            "[-title] <title> "+
 124                            "[-desc | -description] <description> "+
 125                            "\n    "+
 126                            "[-loop] <duration> [-loopdef | -loopdefault] "+
 127                            "");
 128         System.out.println("        -list      "+
 129                            "List the option settings on stdout");
 130         System.out.println("        -gui       "+
 131                            "Run the program in interactive mode (launch GUI)");
 132         System.out.println("        -batch     "+
 133                            "Run the program in batch mode (do not launch GUI)");
 134         System.out.println("        -noshow    "+
 135                            "Do not show output on the screen (batch mode)");
 136         System.out.println("        -nosave    "+
 137                            "Do not show save results to a file (batch mode)");
 138         System.out.println("        -report    "+
 139                            "Rate format to report 'X per Y' (default u/s)");
 140         System.out.println("                   "+
 141                            "  N = report in single units or ops");
 142         System.out.println("                   "+
 143                            "  M = report in millions of units or ops");
 144         System.out.println("                   "+
 145                            "  K = report in thousands of units or ops");
 146         System.out.println("                   "+
 147                            "  A = (auto) M or K as needed");
 148         System.out.println("                   "+
 149                            "  U = units as defined by the operation");
 150         System.out.println("                   "+
 151                            "  O = operations");
 152         System.out.println("                   "+
 153                            "  s = report by whole seconds");
 154         System.out.println("                   "+
 155                            "  m = report by milliseconds");
 156         System.out.println("                   "+
 157                            "  u = report by microseconds");
 158         System.out.println("                   "+
 159                            "  n = report by nanoseconds");
 160         System.out.println("                   "+
 161                            "  a = (auto) milli/micro/nanoseconds as needed");
 162         System.out.println("                   "+
 163                            "  / = invert (N/sec or secs/N)");
 164         System.out.println("        -usage     "+
 165                            "Print out this usage message");
 166         System.out.println("        -saveres   "+
 167                            "Save the results to the indicated file");
 168         System.out.println("        -appres    "+
 169                            "Append the results to the indicated file");
 170         System.out.println("        -title     "+
 171                            "Use the title for the saved results");
 172         System.out.println("        -desc      "+
 173                            "Use the description for the saved results");
 174         System.out.println("        -loop      "+
 175                            "Loop for the specified duration"+
 176                            "\n                   "+
 177                            "Duration specified as :"+
 178                            "\n                     "+
 179                            "<days>d / <hours>h / <minutes>m / dd:hh:mm");
 180         System.out.println("        -loopdef   "+
 181                            "Loop for a default duration of 72 hours");
 182 
 183         System.exit(exitcode);
 184     }
 185 
 186     public static void main(String argv[]) {
 187         init();
 188         TestEnvironment.init();
 189         Result.init();
 190 
 191         Destinations.init();
 192         GraphicsTests.init();
 193         RenderTests.init();
 194         PixelTests.init();
 195         ImageTests.init();
 196         MiscTests.init();
 197         TextTests.init();
 198         TextRenderTests.init();
 199         TextMeasureTests.init();
 200         TextConstructionTests.init();
 201         IIOTests.init();
 202 
 203         boolean gui = true;
 204         boolean showresults = true;
 205         boolean saveresults = true;
 206         String resfilename = null;
 207         String title = null;
 208         String desc = null;
 209         boolean appendres = false;
 210         long requiredLoopTime = 259200000; // 72 hrs * 60 * 60 * 1000
 211         for (int i = 0; i < argv.length; i++) {
 212             String arg = argv[i];
 213             if (arg.equalsIgnoreCase("-list")) {
 214                 PrintWriter pw = new PrintWriter(System.out);
 215                 Node.Iterator iter = Group.root.getRecursiveChildIterator();
 216                 while (iter.hasNext()) {
 217                     Node n = iter.next();
 218                     n.write(pw);
 219                 }
 220                 pw.flush();
 221             } else if (arg.equalsIgnoreCase("-gui") ||
 222                        arg.equalsIgnoreCase("-interactive"))
 223             {
 224                 gui = true;
 225             } else if (arg.equalsIgnoreCase("-batch")) {
 226                 gui = false;
 227             } else if (arg.equalsIgnoreCase("-noshow")) {
 228                 showresults = false;
 229             } else if (arg.equalsIgnoreCase("-nosave")) {
 230                 saveresults = false;
 231             } else if (arg.equalsIgnoreCase("-usage") ||
 232                        arg.equalsIgnoreCase("-help"))
 233             {
 234                 usage(0);
 235             } else if (arg.equalsIgnoreCase("-loadoptions") ||
 236                        arg.equalsIgnoreCase("-loadopts"))
 237             {
 238                 if (++i < argv.length) {
 239                     String file = argv[i];
 240                     String reason = loadOptions(file);
 241                     if (reason != null) {
 242                         System.err.println(reason);
 243                         System.exit(1);
 244                     }
 245                 } else {
 246                     usage(1);
 247                 }
 248             } else if (arg.equalsIgnoreCase("-saveoptions") ||
 249                        arg.equalsIgnoreCase("-saveopts"))
 250             {
 251                 if (++i < argv.length) {
 252                     String file = argv[i];
 253                     String reason = saveOptions(file);
 254                     if (reason != null) {
 255                         System.err.println(reason);
 256                         System.exit(1);
 257                     }
 258                 } else {
 259                     usage(1);
 260                 }
 261             } else if (arg.equalsIgnoreCase("-saveresults") ||
 262                        arg.equalsIgnoreCase("-saveres") ||
 263                        arg.equalsIgnoreCase("-appendresults") ||
 264                        arg.equalsIgnoreCase("-appres"))
 265             {
 266                 if (++i < argv.length) {
 267                     resfilename = argv[i];
 268                     appendres = arg.substring(0, 4).equalsIgnoreCase("-app");
 269                 } else {
 270                     usage(1);
 271                 }
 272             } else if (arg.equalsIgnoreCase("-title")) {
 273                 if (++i < argv.length) {
 274                     title = argv[i];
 275                 } else {
 276                     usage(1);
 277                 }
 278             } else if (arg.equalsIgnoreCase("-desc") ||
 279                        arg.equalsIgnoreCase("-description"))
 280             {
 281                 if (++i < argv.length) {
 282                     desc = argv[i];
 283                 } else {
 284                     usage(1);
 285                 }
 286             } else if (arg.equalsIgnoreCase("-loopdef") ||
 287                        arg.equalsIgnoreCase("-loopdefault"))
 288             {
 289                 requiredLoopTime = 259200000; // 72 hrs * 60 * 60 * 1000
 290                 J2DBench.looping = true;
 291             } else if (arg.equalsIgnoreCase("-loop")) {
 292 
 293                 if (++i >= argv.length) {
 294                     usage(1);
 295                 }
 296 
 297                 J2DBench.looping = true;
 298 
 299                 /*
 300                  * d or D    ->  Days
 301                  * h or H    ->  Hours
 302                  * m or M    ->  Minutes
 303                  * dd:hh:mm  ->  Days:Hours:Minutes
 304                  */
 305 
 306                 if (argv[i].indexOf(":") >= 0) {
 307 
 308                     String values[] = argv[i].split(":");
 309                     int intVals[] = new int[3];
 310 
 311                     for(int j=0; j<values.length; j++) {
 312                         try {
 313                             intVals[j] = Integer.parseInt(values[j]);
 314                         } catch(Exception e) {}
 315                     }
 316 
 317                     System.out.println("\nLoop for " + intVals[0] +
 318                                        " days " + intVals[1] +
 319                                        " hours and " + intVals[2] + " minutes.\n");
 320 
 321                     requiredLoopTime = ((intVals[0] * 24 * 60 * 60) +
 322                                         (intVals[1] * 60 * 60) +
 323                                         (intVals[2] * 60)) * 1000;
 324 
 325                 } else {
 326 
 327                     String type = argv[i].substring(argv[i].length() - 1);
 328 
 329                     int multiplyWith = 1;
 330 
 331                     if (type.equalsIgnoreCase("d")) {
 332                         multiplyWith = 24 * 60 * 60;
 333                     } else if (type.equalsIgnoreCase("h")) {
 334                         multiplyWith = 60 * 60;
 335                     } else if (type.equalsIgnoreCase("m")) {
 336                         multiplyWith = 60;
 337                     } else {
 338                         System.err.println("Invalid \"-loop\" option specified.");
 339                         usage(1);
 340                     }
 341 
 342                     int val = 1;
 343                     try {
 344                         val = Integer.parseInt(argv[i].substring(0, argv[i].length() - 1));
 345                     } catch(Exception e) {
 346                         System.err.println("Invalid \"-loop\" option specified.");
 347                         usage(1);
 348                     }
 349 
 350                     requiredLoopTime = val * multiplyWith * 1000;
 351                 }
 352 
 353            } else if (arg.length() > 8 &&
 354                         arg.substring(0, 8).equalsIgnoreCase("-report:"))
 355            {
 356                 String error = Result.parseRateOpt(arg.substring(8));
 357                 if (error != null) {
 358                      System.err.println("Invalid rate: "+error);
 359                      usage(1);
 360                 }
 361             } else {
 362                 String reason = Group.root.setOption(arg);
 363                 if (reason != null) {
 364                     System.err.println("Option "+arg+" ignored: "+reason);
 365                 }
 366             }
 367         }
 368         if (verbose.isEnabled()) {
 369             Group.root.traverse(new Node.Visitor() {
 370                 public void visit(Node node) {
 371                     System.out.println(node);
 372                 }
 373             });
 374         }
 375 
 376         if (gui) {
 377             startGUI();
 378         } else {
 379 
 380             long start = System.currentTimeMillis();
 381 
 382             int nLoopCount = 1;
 383 
 384             if (saveresults) {
 385                 if (title == null) {
 386                     title = inputUserStr("title");
 387                 }
 388                 if (desc == null) {
 389                     desc = inputUserStr("description");
 390                 }
 391             }
 392 
 393             PrintWriter writer = null;
 394 
 395             if (J2DBench.looping) {
 396 
 397                 System.out.println("\nAbout to run tests for : " +
 398                                    (requiredLoopTime/1000) + " seconds.\n");
 399 
 400                 if(resfilename != null) {
 401 
 402                     try {
 403                         String loopReportFileName =
 404                             resfilename.substring(0, resfilename.lastIndexOf(".xml"));
 405                         writer = new PrintWriter(
 406                             new FileWriter(loopReportFileName + "_Loop.html"));
 407                         writer.println("<html><head><title>" + title + "</title></head>");
 408                         writer.println("<body bgcolor=\"#ffffff\"><hr size=\"1\">");
 409                         writer.println("<center><h2>" + title + "</h2>");
 410                         writer.println("</center><hr size=\"1\"><br>");
 411                         writer.flush();
 412                     } catch(IOException ioe) {
 413                         ioe.printStackTrace();
 414                         System.err.println("\nERROR : Could not create Loop-Report. Exit");
 415                         System.exit(1);
 416                     }
 417                 }
 418             }
 419 
 420             do {
 421 
 422                 Date loopStart = new Date();
 423                 if (J2DBench.looping) {
 424                     writer.println("<b>Loop # " + nLoopCount + "</b><br>");
 425                     writer.println("<b>Start : </b>" + sdf.format(loopStart) + "<br>");
 426                     writer.flush();
 427                 }
 428 
 429                 runTests(showresults);
 430                 if (saveresults) {
 431                     if (resfilename != null) {
 432                         lastResults.setTitle(title);
 433                         lastResults.setDescription(desc);
 434                         String reason = saveResults(resfilename, appendres);
 435                         if (reason != null) {
 436                             System.err.println(reason);
 437                         }
 438                     } else {
 439                         saveResults(title, desc);
 440                     }
 441                 }
 442 
 443                 if (J2DBench.looping) {
 444 
 445                     Date loopEnd = new Date();
 446 
 447                     System.out.println("\n================================================================");
 448                     System.out.println("-- Completed Loop " + nLoopCount + " at " + sdf.format(loopEnd) + " --");
 449                     System.out.println("================================================================\n");
 450 
 451                     writer.println("<b>End : </b>" + sdf.format(loopEnd) + "<br>");
 452                     writer.println("<b>Duration </b>: " + (loopEnd.getTime() - loopStart.getTime())/1000 + " Seconds<br>");
 453                     writer.println("<b>Total : " + (loopEnd.getTime() - start)/1000 + " Seconds</b><br>");
 454                     writer.println("</center><hr size=\"1\">");
 455                     writer.flush();
 456 
 457                     if ((loopEnd.getTime() - start) > requiredLoopTime) {
 458                         break;
 459                     }
 460 
 461                     //Append results for looping - mode
 462                     appendres = true;
 463 
 464                     nLoopCount++;
 465                 }
 466 
 467             } while(J2DBench.looping);
 468 
 469             if (J2DBench.looping) {
 470                 writer.println("</html>");
 471                 writer.flush();
 472                 writer.close();
 473             }
 474         }
 475     }
 476 
 477     public static String loadOptions(String filename) {
 478         FileReader fr;
 479         try {
 480             fr = new FileReader(filename);
 481         } catch (FileNotFoundException e) {
 482             return "file "+filename+" not found";
 483         }
 484         return loadOptions(fr, filename);
 485     }
 486 
 487     public static String loadOptions(File file) {
 488         FileReader fr;
 489         try {
 490             fr = new FileReader(file);
 491         } catch (FileNotFoundException e) {
 492             return "file "+file.getPath()+" not found";
 493         }
 494         return loadOptions(fr, file.getPath());
 495     }
 496 
 497     public static String loadOptions(FileReader fr, String filename) {
 498         LineNumberReader lnr = new LineNumberReader(fr);
 499         Group.restoreAllDefaults();
 500         String line;
 501         try {
 502             while ((line = lnr.readLine()) != null) {
 503                 String reason = Group.root.setOption(line);
 504                 if (reason != null) {
 505                     System.err.println("Option "+line+
 506                                        " at line "+lnr.getLineNumber()+
 507                                        " ignored: "+reason);
 508                 }
 509             }
 510         } catch (IOException e) {
 511             Group.restoreAllDefaults();
 512             return ("IO Error reading "+filename+
 513                     " at line "+lnr.getLineNumber());
 514         }
 515         return null;
 516     }
 517 
 518     public static String saveOptions(String filename) {
 519         return saveOptions(new File(filename));
 520     }
 521 
 522     public static String saveOptions(File file) {
 523         if (file.exists()) {
 524             if (!file.isFile()) {
 525                 return "Cannot save options to a directory!";
 526             }
 527             int ret = JOptionPane.showOptionDialog
 528                 (guiFrame,
 529                  new String[] {
 530                      "The file '"+file.getName()+"' already exists!",
 531                      "",
 532                      "Do you wish to overwrite this file?",
 533                  },
 534                  "File exists!",
 535                  JOptionPane.DEFAULT_OPTION,
 536                  JOptionPane.WARNING_MESSAGE,
 537                  null, new String[] {
 538                      "Overwrite",
 539                      "Cancel",
 540                  }, "Cancel");
 541             if (ret == 1) {
 542                 return null;
 543             }
 544         }
 545         FileWriter fw;
 546         try {
 547             fw = new FileWriter(file);
 548         } catch (IOException e) {
 549             return "Error opening option file "+file.getPath();
 550         }
 551         return saveOptions(fw, file.getPath());
 552     }
 553 
 554     public static String saveOptions(FileWriter fw, String filename) {
 555         PrintWriter pw = new PrintWriter(fw);
 556         Group.writeAll(pw);
 557         return null;
 558     }
 559 
 560     public static JFileChooser theFC;
 561     public static JFileChooser getFileChooser() {
 562         if (theFC == null) {
 563             theFC = new JFileChooser(System.getProperty("user.dir"));
 564         }
 565         theFC.rescanCurrentDirectory();
 566         return theFC;
 567     }
 568 
 569     public static ResultSet lastResults;
 570     public static boolean saveOrDiscardLastResults() {
 571         if (lastResults != null) {
 572             int ret = JOptionPane.showConfirmDialog
 573                 (guiFrame,
 574                  "The results of the last test will be "+
 575                  "discarded if you continue!  Do you want "+
 576                  "to save them?",
 577                  "Discard last results?",
 578                  JOptionPane.YES_NO_CANCEL_OPTION);
 579             if (ret == JOptionPane.CANCEL_OPTION) {
 580                 return false;
 581             } else if (ret == JOptionPane.YES_OPTION) {
 582                 if (saveResults()) {
 583                     lastResults = null;
 584                 } else {
 585                     return false;
 586                 }
 587             }
 588         }
 589         return true;
 590     }
 591 
 592     public static String inputUserStr(String type) {
 593         return JOptionPane.showInputDialog("Enter a "+
 594                                            type+
 595                                            " for this result set:");
 596     }
 597 
 598     public static boolean saveResults() {
 599         return saveResults(inputUserStr("title"), inputUserStr("description"));
 600     }
 601 
 602     public static boolean saveResults(String title, String desc) {
 603         lastResults.setTitle(title);
 604         lastResults.setDescription(desc);
 605         JFileChooser fc = getFileChooser();
 606         int ret = fc.showSaveDialog(guiFrame);
 607         if (ret == JFileChooser.APPROVE_OPTION) {
 608             File file = fc.getSelectedFile();
 609             boolean append = false;
 610             if (file.exists()) {
 611                 if (!file.isFile()) {
 612                     System.err.println("Cannot save results to a directory!");
 613                     return false;
 614                 }
 615                 ret = JOptionPane.showOptionDialog
 616                     (guiFrame,
 617                      new String[] {
 618                          "The file '"+file.getName()+"' already exists!",
 619                          "",
 620                          "Do you wish to overwrite or append to this file?",
 621                      },
 622                      "File exists!",
 623                      JOptionPane.DEFAULT_OPTION,
 624                      JOptionPane.WARNING_MESSAGE,
 625                      null, new String[] {
 626                          "Overwrite",
 627                          "Append",
 628                          "Cancel",
 629                      }, "Cancel");
 630                 if (ret == 0) {
 631                     append = false;
 632                 } else if (ret == 1) {
 633                     append = true;
 634                 } else {
 635                     return false;
 636                 }
 637             }
 638             String reason = saveResults(file, append);
 639             if (reason == null) {
 640                 return true;
 641             } else {
 642                 System.err.println(reason);
 643             }
 644         }
 645         return false;
 646     }
 647 
 648     public static String saveResults(String filename, boolean append) {
 649         FileWriter fw;
 650         try {
 651             fw = new FileWriter(filename, append);
 652         } catch (IOException e) {
 653             return "Error opening results file "+filename;
 654         }
 655         return saveResults(fw, filename, append);
 656     }
 657 
 658     public static String saveResults(File file, boolean append) {
 659         FileWriter fw;
 660         try {
 661             fw = new FileWriter(file, append);
 662         } catch (IOException e) {
 663             return "Error opening results file "+file.getName();
 664         }
 665         return saveResults(fw, file.getName(), append);
 666     }
 667 
 668     public static String saveResults(FileWriter fw, String filename,
 669                                      boolean append)
 670     {
 671         PrintWriter pw = new PrintWriter(fw);
 672         if (!append) {
 673             pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
 674             pw.println("<!--For Entertainment Purposes Only-->");
 675         }
 676         pw.println();
 677         lastResults.write(pw);
 678         pw.flush();
 679         pw.close();
 680         return null;
 681     }
 682 
 683     public static void startGUI() {
 684         final JFrame f = new JFrame("J2DBench") {
 685             public Dimension getPreferredSize() {
 686                 Dimension pref = super.getPreferredSize();
 687                 pref.width = Math.max(pref.width, 800);
 688                 pref.height = Math.max(pref.height, 600);
 689                 return pref;
 690             }
 691         };
 692         guiFrame = f;
 693         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 694         f.getContentPane().setLayout(new BorderLayout());
 695         f.getContentPane().add(Group.root.getJComponent(), BorderLayout.CENTER);
 696         JPanel p = new JPanel();
 697         p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
 698         JButton b = new JButton("Run Tests...");
 699         b.addActionListener(new ActionListener() {
 700             public void actionPerformed(ActionEvent e) {
 701                 if (!saveOrDiscardLastResults()) {
 702                     return;
 703                 }
 704                 if (verbose.isEnabled()) {
 705                     System.out.println(e);
 706                     System.out.println("running tests...");
 707                 }
 708                 new Thread(new Runnable() {
 709                     public void run() {
 710                         runTests(true);
 711                     }
 712                 }).start();
 713                 if (verbose.isEnabled()) {
 714                     System.out.println("done");
 715                 }
 716             }
 717         });
 718         p.add(b);
 719 
 720         b = new JButton("Load Options");
 721         b.addActionListener(new ActionListener() {
 722             public void actionPerformed(ActionEvent e) {
 723                 JFileChooser fc = getFileChooser();
 724                 int ret = fc.showOpenDialog(f);
 725                 if (ret == JFileChooser.APPROVE_OPTION) {
 726                     String reason = loadOptions(fc.getSelectedFile());
 727                     if (reason != null) {
 728                         System.err.println(reason);
 729                     }
 730                 }
 731             }
 732         });
 733         p.add(b);
 734 
 735         b = new JButton("Save Options");
 736         b.addActionListener(new ActionListener() {
 737             public void actionPerformed(ActionEvent e) {
 738                 JFileChooser fc = getFileChooser();
 739                 int ret = fc.showSaveDialog(f);
 740                 if (ret == JFileChooser.APPROVE_OPTION) {
 741                     String reason = saveOptions(fc.getSelectedFile());
 742                     if (reason != null) {
 743                         System.err.println(reason);
 744                     }
 745                 }
 746             }
 747         });
 748         p.add(b);
 749 
 750         b = new JButton("Save Results");
 751         b.addActionListener(new ActionListener() {
 752             public void actionPerformed(ActionEvent e) {
 753                 if (saveResults()) {
 754                     lastResults = null;
 755                 }
 756             }
 757         });
 758         p.add(b);
 759 
 760         b = new JButton("Quit");
 761         b.addActionListener(new ActionListener() {
 762             public void actionPerformed(ActionEvent e) {
 763                 if (!saveOrDiscardLastResults()) {
 764                     return;
 765                 }
 766                 System.exit(0);
 767             }
 768         });
 769         p.add(b);
 770 
 771         f.getContentPane().add(p, BorderLayout.SOUTH);
 772         f.pack();
 773         f.show();
 774     }
 775 
 776     public static void runTests(boolean showresults) {
 777         final TestEnvironment env = new TestEnvironment();
 778         Frame f = null;
 779         if (showresults) {
 780             f = new Frame("J2DBench test run");
 781             f.addWindowListener(new WindowAdapter() {
 782                 public void windowClosing(WindowEvent e) {
 783                     env.stop();
 784                 }
 785             });
 786             f.add(env.getCanvas());
 787             f.pack();
 788             f.show();
 789         }
 790         for (int i = 0; i < 5; i++) {
 791             env.idle();
 792         }
 793         env.runAllTests();
 794         if (showresults) {
 795             f.hide();
 796             f.dispose();
 797         }
 798         lastResults = env.results;
 799         if (J2DBench.printresults.isEnabled()) {
 800             System.out.println();
 801         }
 802         System.out.println("All test results:");
 803         env.summarize();
 804         System.out.println();
 805     }
 806 }