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