1 /*
   2  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  *
  26  *
  27  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  28  * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
  29  *
  30  * Portions copyright (c) 2007 Sun Microsystems, Inc.
  31  * All Rights Reserved.
  32  *
  33  * The original version of this source code and documentation
  34  * is copyrighted and owned by Taligent, Inc., a wholly-owned
  35  * subsidiary of IBM. These materials are provided under terms
  36  * of a License Agreement between Taligent and Sun. This technology
  37  * is protected by multiple US and International patents.
  38  *
  39  * This notice and attribution to Taligent may not be removed.
  40  * Taligent is a registered trademark of Taligent, Inc.
  41  *
  42  * Permission to use, copy, modify, and distribute this software
  43  * and its documentation for NON-COMMERCIAL purposes and without
  44  * fee is hereby granted provided that this copyright notice
  45  * appears in all copies. Please refer to the file "copyright.html"
  46  * for further important copyright and licensing information.
  47  *
  48  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  49  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  50  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  51  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  52  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  53  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  54  *
  55  */
  56 
  57 import java.lang.reflect.*;
  58 import java.util.Hashtable;
  59 import java.util.Enumeration;
  60 import java.util.Vector;
  61 import java.io.*;
  62 import java.text.*;
  63 
  64 /**
  65  * LocaleTestFmwk is a base class for tests that can be run conveniently from
  66  * the command line as well as under the Java test harness.
  67  * <p>
  68  * Sub-classes implement a set of methods named Test<something>. Each
  69  * of these methods performs some test. Test methods should indicate
  70  * errors by calling either err or errln.  This will increment the
  71  * errorCount field and may optionally print a message to the log.
  72  * Debugging information may also be added to the log via the log
  73  * and logln methods.  These methods will add their arguments to the
  74  * log only if the test is being run in verbose mode.
  75  */
  76 public class LocaleTestFmwk {
  77     //------------------------------------------------------------------------
  78     // Everything below here is boilerplate code that makes it possible
  79     // to add a new test by simply adding a function to an existing class
  80     //------------------------------------------------------------------------
  81 
  82     protected LocaleTestFmwk() {
  83         // Create a hashtable containing all the test methods.
  84         testMethods = new Hashtable();
  85         Method[] methods = getClass().getDeclaredMethods();
  86         for( int i=0; i<methods.length; i++ ) {
  87             if( methods[i].getName().startsWith("Test")
  88                     || methods[i].getName().startsWith("test")) {
  89                 testMethods.put( methods[i].getName(), methods[i] );
  90             }
  91         }
  92     }
  93 
  94     protected void run(String[] args) throws Exception
  95     {
  96         System.out.println(getClass().getName() + " {");
  97         indentLevel++;
  98 
  99         // Set up the log and reference streams.  We use PrintWriters in order to
 100         // take advantage of character conversion.  The JavaEsc converter will
 101         // convert Unicode outside the ASCII range to Java's \\uxxxx notation.
 102         log = new PrintWriter(System.out,true);
 103 
 104         // Parse the test arguments.  They can be either the flag
 105         // "-verbose" or names of test methods. Create a list of
 106         // tests to be run.
 107         Vector testsToRun = new Vector( args.length );
 108         for( int i=0; i<args.length; i++ ) {
 109             if( args[i].equals("-verbose") ) {
 110                 verbose = true;
 111             }
 112             else if( args[i].equals("-prompt") ) {
 113                 prompt = true;
 114             } else if (args[i].equals("-nothrow")) {
 115                 nothrow = true;
 116             } else if (args[i].equals("-exitcode")) {
 117                 exitcode = true;
 118             } else {
 119                 Object m = testMethods.get( args[i] );
 120                 if( m != null ) {
 121                     testsToRun.addElement( m );
 122                 }
 123                 else {
 124                     usage();
 125                     return;
 126                 }
 127             }
 128         }
 129 
 130         // If no test method names were given explicitly, run them all.
 131         if( testsToRun.size() == 0 ) {
 132             Enumeration methodNames = testMethods.elements();
 133             while( methodNames.hasMoreElements() ) {
 134                 testsToRun.addElement( methodNames.nextElement() );
 135             }
 136         }
 137 
 138         // Run the list of tests given in the test arguments
 139         for( int i=0; i<testsToRun.size(); i++ ) {
 140             int oldCount = errorCount;
 141 
 142             Method testMethod = (Method)testsToRun.elementAt(i);
 143             writeTestName(testMethod.getName());
 144 
 145             try {
 146                 testMethod.invoke(this, new Object[0]);
 147             }
 148             catch( IllegalAccessException e ) {
 149                 errln("Can't acces test method " + testMethod.getName());
 150             }
 151             catch( InvocationTargetException e ) {
 152                 errln("Uncaught exception thrown in test method "
 153                                + testMethod.getName());
 154                 e.getTargetException().printStackTrace(this.log);
 155             }
 156             writeTestResult(errorCount - oldCount);
 157         }
 158         indentLevel--;
 159         writeTestResult(errorCount);
 160 
 161         if (prompt) {
 162             System.out.println("Hit RETURN to exit...");
 163             try {
 164                 System.in.read();
 165             }
 166             catch (IOException e) {
 167                 System.out.println("Exception: " + e.toString() + e.getMessage());
 168             }
 169         }
 170         if (nothrow) {
 171             if (exitcode) {
 172                 System.exit(errorCount);
 173             }
 174             if (errorCount > 0) {
 175                 throw new IllegalArgumentException("encountered " + errorCount + " errors");
 176             }
 177         }
 178     }
 179 
 180     /**
 181      * Adds given string to the log if we are in verbose mode.
 182      */
 183     protected void log( String message ) {
 184         if( verbose ) {
 185             indent(indentLevel + 1);
 186             log.print( message );
 187         }
 188     }
 189 
 190     protected void logln( String message ) {
 191         log(message + System.getProperty("line.separator"));
 192     }
 193 
 194     /**
 195      * Report an error
 196      */
 197     protected void err( String message ) {
 198         errorCount++;
 199         indent(indentLevel + 1);
 200         log.print( message );
 201         log.flush();
 202 
 203         if (!nothrow) {
 204             throw new RuntimeException(message);
 205         }
 206     }
 207 
 208     protected void errln( String message ) {
 209         err(message + System.getProperty("line.separator"));
 210     }
 211 
 212 
 213     protected void writeTestName(String testName) {
 214         indent(indentLevel);
 215         log.print(testName);
 216         log.flush();
 217         needLineFeed = true;
 218     }
 219 
 220     protected void writeTestResult(int count) {
 221         if (!needLineFeed) {
 222             indent(indentLevel);
 223             log.print("}");
 224         }
 225         needLineFeed = false;
 226 
 227         if (count != 0)
 228             log.println(" FAILED");
 229         else
 230             log.println(" Passed");
 231     }
 232 
 233     private final void indent(int distance) {
 234         if (needLineFeed) {
 235             log.println(" {");
 236             needLineFeed = false;
 237         }
 238         log.print(spaces.substring(0, distance * 2));
 239     }
 240 
 241     /**
 242      * Print a usage message for this test class.
 243      */
 244     void usage() {
 245         System.out.println(getClass().getName() +
 246                             ": [-verbose] [-nothrow] [-exitcode] [-prompt] [test names]");
 247 
 248         System.out.println("test names:");
 249         Enumeration methodNames = testMethods.keys();
 250         while( methodNames.hasMoreElements() ) {
 251             System.out.println("\t" + methodNames.nextElement() );
 252         }
 253     }
 254 
 255     private boolean     prompt = false;
 256     private boolean     nothrow = false;
 257     private boolean     exitcode = false;
 258     protected boolean   verbose = false;
 259 
 260     private PrintWriter log;
 261     private int         indentLevel = 0;
 262     private boolean     needLineFeed = false;
 263     private int         errorCount = 0;
 264 
 265     private Hashtable testMethods;
 266     private final String spaces = "                                          ";
 267 }