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 }