1 /* 2 * Copyright (c) 1999, 2020, 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 * (C) Copyright IBM Corp. 1999 - All Rights Reserved 26 * 27 * The original version of this source code and documentation is 28 * copyrighted and owned by IBM. These materials are provided 29 * under terms of a License Agreement between IBM and Sun. 30 * This technology is protected by multiple US and International 31 * patents. This notice and attribution to IBM may not be removed. 32 */ 33 34 import java.lang.reflect.*; 35 import java.util.Hashtable; 36 import java.util.Enumeration; 37 import java.util.Vector; 38 import java.io.*; 39 import java.text.*; 40 41 /** 42 * RBTestFmwk is a base class for tests that can be run conveniently from 43 * the command line as well as under the Java test harness. 44 * <p> 45 * Sub-classes implement a set of methods named Test<something>. Each 46 * of these methods performs some test. Test methods should indicate 47 * errors by calling either err or errln. This will increment the 48 * errorCount field and may optionally print a message to the log. 49 * Debugging information may also be added to the log via the log 50 * and logln methods. These methods will add their arguments to the 51 * log only if the test is being run in verbose mode. 52 */ 53 public class TestFmwk { 54 //------------------------------------------------------------------------ 55 // Everything below here is boilerplate code that makes it possible 56 // to add a new test by simply adding a function to an existing class 57 //------------------------------------------------------------------------ 58 59 protected TestFmwk() { 60 // Create a hashtable containing all the test methods. 61 testMethods = new Hashtable(); 62 Method[] methods = getClass().getDeclaredMethods(); 63 for( int i=0; i<methods.length; i++ ) { 64 if( methods[i].getName().startsWith("Test") 65 || methods[i].getName().startsWith("test") ) { 66 testMethods.put( methods[i].getName(), methods[i] ); 67 } 68 } 69 } 70 71 protected void run(String[] args) throws Exception 72 { 73 System.out.println(getClass().getName() + " {"); 74 indentLevel++; 75 76 // Set up the log and reference streams. We use PrintWriters in order to 77 // take advantage of character conversion. The JavaEsc converter will 78 // convert Unicode outside the ASCII range to Java's \\uxxxx notation. 79 log = new PrintWriter(System.out,true); 80 81 // Parse the test arguments. They can be either the flag 82 // "-verbose" or names of test methods. Create a list of 83 // tests to be run. 84 Vector testsToRun = new Vector( args.length ); 85 for( int i=0; i<args.length; i++ ) { 86 if( args[i].equals("-verbose") ) { 87 verbose = true; 88 } 89 else if( args[i].equals("-prompt") ) { 90 prompt = true; 91 } else if (args[i].equals("-nothrow")) { 92 nothrow = true; 93 } else { 94 Object m = testMethods.get( args[i] ); 95 if( m != null ) { 96 testsToRun.addElement( m ); 97 } 98 else { 99 usage(); 100 return; 101 } 102 } 103 } 104 105 // If no test method names were given explicitly, run them all. 106 if( testsToRun.size() == 0 ) { 107 Enumeration methodNames = testMethods.elements(); 108 while( methodNames.hasMoreElements() ) { 109 testsToRun.addElement( methodNames.nextElement() ); 110 } 111 } 112 113 // Run the list of tests given in the test arguments 114 for( int i=0; i<testsToRun.size(); i++ ) { 115 int oldCount = errorCount; 116 117 Method testMethod = (Method)testsToRun.elementAt(i); 118 writeTestName(testMethod.getName()); 119 120 try { 121 testMethod.invoke(this, new Object[0]); 122 } 123 catch( IllegalAccessException e ) { 124 errln("Can't acces test method " + testMethod.getName()); 125 } 126 catch( InvocationTargetException e ) { 127 errln("Uncaught exception thrown in test method " 128 + testMethod.getName()); 129 e.getTargetException().printStackTrace(this.log); 130 } 131 writeTestResult(errorCount - oldCount); 132 } 133 indentLevel--; 134 writeTestResult(errorCount); 135 136 if (prompt) { 137 System.out.println("Hit RETURN to exit..."); 138 try { 139 System.in.read(); 140 } 141 catch (IOException e) { 142 System.out.println("Exception: " + e.toString() + e.getMessage()); 143 } 144 } 145 if (nothrow) { 146 System.exit(errorCount); 147 } 148 } 149 150 /** 151 * Adds given string to the log if we are in verbose mode. 152 */ 153 protected void log( String message ) { 154 if( verbose ) { 155 indent(indentLevel + 1); 156 log.print( message ); 157 log.flush(); 158 } 159 } 160 161 protected void logln( String message ) { 162 log(message + System.getProperty("line.separator")); 163 } 164 165 /** 166 * Report an error 167 */ 168 protected void err( String message ) { 169 errorCount++; 170 indent(indentLevel + 1); 171 log.print( message ); 172 log.flush(); 173 174 if (!nothrow) { 175 throw new RuntimeException(message); 176 } 177 } 178 179 protected void errln( String message ) { 180 err(message + System.getProperty("line.separator")); 181 } 182 183 184 protected void writeTestName(String testName) { 185 indent(indentLevel); 186 log.print(testName); 187 log.flush(); 188 needLineFeed = true; 189 } 190 191 protected void writeTestResult(int count) { 192 if (!needLineFeed) { 193 indent(indentLevel); 194 log.print("}"); 195 } 196 needLineFeed = false; 197 198 if (count != 0) 199 log.println(" FAILED"); 200 else 201 log.println(" Passed"); 202 } 203 204 private final void indent(int distance) { 205 if (needLineFeed) { 206 log.println(" {"); 207 needLineFeed = false; 208 } 209 log.print(spaces.substring(0, distance * 2)); 210 } 211 212 /** 213 * Print a usage message for this test class. 214 */ 215 void usage() { 216 System.out.println(getClass().getName() + 217 ": [-verbose] [-nothrow] [-prompt] [test names]"); 218 219 System.out.println("test names:"); 220 Enumeration methodNames = testMethods.keys(); 221 while( methodNames.hasMoreElements() ) { 222 System.out.println("\t" + methodNames.nextElement() ); 223 } 224 } 225 226 private boolean prompt = false; 227 private boolean nothrow = false; 228 protected boolean verbose = false; 229 230 private PrintWriter log; 231 private int indentLevel = 0; 232 private boolean needLineFeed = false; 233 private int errorCount = 0; 234 235 private Hashtable testMethods; 236 private final String spaces = " "; 237 }