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