1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 package complexlib; 24 25 import java.lang.reflect.Method; 26 import share.DescEntry; 27 import lib.TestParameters; 28 import lib.StatusException; 29 import share.LogWriter; 30 import share.ComplexTest; 31 import java.io.PrintWriter; 32 33 /** 34 * Base class for all complex tests. 35 */ 36 public abstract class ComplexTestCase extends Assurance implements ComplexTest 37 { 38 39 /** The test parameters **/ 40 protected static TestParameters param = null; 41 /** Log writer **/ 42 protected static LogWriter log = null; 43 /** 44 * The method name which will be written into f.e. the data base 45 **/ 46 protected String mTestMethodName = null; 47 /** Maximal time one method is allowed to execute 48 * Can be set with parameter 'ThreadTimeOut' 49 **/ 50 protected int m_nThreadTimeOut = 0; 51 /** Continue a test even if it did fail **/ 52 // public static final boolean CONTINUE = true; 53 54 /** End a test if it did fail **/ 55 public static final boolean BREAK = true; 56 57 private boolean m_bBeforeCalled; 58 59 /** 60 * is called before the real test starts 61 */ before()62 private void before() 63 { 64 try 65 { 66 Method before = this.getClass().getMethod("before", new Class[] {} ); 67 before.invoke(this, new Object[] {} ); 68 69 // beforeWorked = false; 70 m_bBeforeCalled = true; 71 } 72 catch (java.lang.NoSuchMethodException e) 73 { 74 // simply ignore 75 int dummy = 0; 76 m_bBeforeCalled = true; 77 } 78 catch (java.lang.IllegalAccessException e) 79 { 80 log.println("Cannot access the 'before()' method, although it" + " is there. Is this ok?"); 81 } 82 catch (java.lang.reflect.InvocationTargetException e) 83 { 84 Throwable t = e.getTargetException(); 85 if (!(t instanceof RuntimeException) || state) 86 { 87 log.println(t.toString()); 88 if (message == null) 89 { 90 message = "Exception in before() method.\n\r" + t.getMessage(); 91 } 92 state = false; 93 t.printStackTrace((PrintWriter) log); 94 } 95 } 96 97 } 98 99 /** Description entry **/ 100 // protected DescEntry subEntry = null; 101 test_method(DescEntry _entry)102 private void test_method(DescEntry _entry) 103 { 104 105 m_nThreadTimeOut = param.getInt("ThreadTimeOut"); 106 if (m_nThreadTimeOut == 0) 107 { 108 m_nThreadTimeOut = 300000; 109 } 110 111 for (int i = 0; i < _entry.SubEntries.length; i++) 112 { 113 114 DescEntry subEntry = _entry.SubEntries[i]; 115 if (m_bBeforeCalled) 116 { 117 state = true; 118 message = ""; 119 } 120 else 121 { 122 // set all test methods on failed, if 'before()' did not work. 123 subEntry.State = message; 124 subEntry.hasErrorMsg = true; 125 subEntry.ErrorMsg = message; 126 continue; 127 } 128 Method testMethod = null; 129 try 130 { 131 String entryName = subEntry.entryName; 132 Object[] parameter = null; 133 134 if (entryName.indexOf("(") != -1) 135 { 136 String sParameter = (entryName.substring(entryName.indexOf("(") + 1, entryName.indexOf(")"))); 137 mTestMethodName = entryName; 138 parameter = new String[] { sParameter }; 139 entryName = entryName.substring(0, entryName.indexOf("(")); 140 testMethod = this.getClass().getMethod(entryName, new Class[] { String.class }); 141 } 142 else 143 { 144 testMethod = this.getClass().getMethod(entryName, new Class[] {} ); 145 mTestMethodName = entryName; 146 } 147 148 MethodThread th = new MethodThread(testMethod, this, parameter, (java.io.PrintWriter) log); 149 log.println("Starting " + mTestMethodName); 150 th.start(); 151 152 try 153 { 154 // some tests are very dynamic in its exceution time so that 155 // a threadTimeOut fials. In this cases the logging mechanisim 156 // is a usefull way to detect that a office respective a test 157 // is running and not death. 158 // But way ThreadTimeOut? 159 // There exeitsts a complex test which uses no office. Therefore 160 // a logging mechanisim to detect a stalled test. 161 int lastPing = -1; 162 int newPing = 0; 163 164 int sleepingStep = 1000; 165 int factor = 0; 166 167 while (th.isAlive() && (lastPing != newPing || factor * sleepingStep < m_nThreadTimeOut)) 168 { 169 Thread.sleep(sleepingStep); 170 factor++; 171 // if a test starts the office itself it the watcher is a 172 // new one. 173 share.Watcher ow = (share.Watcher) param.get("Watcher"); 174 if (ow != null) 175 { 176 lastPing = newPing; 177 newPing = ow.getPing(); 178 //System.out.println("lastPing: '" + lastPing + "' newPing '" + newPing + "'"); 179 factor = 0; 180 } 181 } 182 } 183 catch (InterruptedException e) 184 { 185 } 186 if (th.isAlive()) 187 { 188 log.println("Destroy " + mTestMethodName); 189 th.destroy(); 190 subEntry.State = "Test did sleep for " + (m_nThreadTimeOut / 1000) + " seconds and has been killed!"; 191 subEntry.hasErrorMsg = true; 192 subEntry.ErrorMsg = subEntry.State; 193 continue; 194 } 195 else 196 { 197 log.println("Finished " + mTestMethodName); 198 if (th.hasErrorMessage()) 199 { 200 subEntry.State = th.getErrorMessage(); 201 subEntry.hasErrorMsg = true; 202 subEntry.ErrorMsg = subEntry.State; 203 continue; 204 } 205 } 206 } 207 catch (java.lang.Exception e) 208 { 209 log.println(e.getClass().getName()); 210 String msg = e.getMessage(); 211 log.println("Message: " + msg); 212 e.printStackTrace((PrintWriter) log); 213 subEntry.State = "SKIPPED.FAILED"; 214 subEntry.hasErrorMsg = true; 215 subEntry.ErrorMsg = (msg == null ? "" : msg); 216 continue; 217 } 218 subEntry.State = (state ? "PASSED.OK" : message); 219 subEntry.hasErrorMsg = !state; 220 subEntry.ErrorMsg = message; 221 } 222 } 223 224 /** 225 * after() is called after the test is done 226 */ after()227 private void after() 228 { 229 if (m_bBeforeCalled) 230 { 231 // the after() method 232 try 233 { 234 Method after = this.getClass().getMethod("after", new Class[] {}); 235 after.invoke(this, new Object[] {} ); 236 } 237 catch (java.lang.NoSuchMethodException e) 238 { 239 // simply ignore 240 } 241 catch (java.lang.IllegalAccessException e) 242 { 243 // simply ignore 244 } 245 catch (java.lang.reflect.InvocationTargetException e) 246 { 247 Throwable t = e.getTargetException(); 248 if (!(t instanceof StatusException)) 249 { 250 log.println(t.toString()); 251 if (message == null) 252 { 253 message = "Exception in after() method.\n\r" + t.getMessage(); 254 } 255 else 256 { 257 message += "Exception in \'after()\' method.\n\r" + t.getMessage(); 258 } 259 log.println("Message: " + message); 260 t.printStackTrace((PrintWriter) log); 261 } 262 } 263 } 264 265 } 266 267 268 269 /** 270 * Call test. It is expected, that an environment is 271 * given to this test. 272 * 273 * @param entry The name of the test method that should be called. 274 * @param environment The environment for the test. 275 */ executeMethods(DescEntry entry, TestParameters environment)276 public void executeMethods(DescEntry entry, TestParameters environment) 277 { 278 m_bBeforeCalled = false; 279 280 // get the environment 281 param = environment; 282 log = entry.Logger; 283 284 285 // start with the before() method 286 before(); 287 288 //executeMethodTests 289 test_method(entry); 290 291 // cleanup 292 after(); 293 } 294 295 296 /** 297 * Implement this method in the Complex test. 298 * @return All test method names. 299 */ getTestMethodNames()300 public abstract String[] getTestMethodNames(); 301 302 /** 303 * Return a name for the test or tested object. 304 * Override to give an own name. 305 * @return As default, the name of this class. 306 */ getTestObjectName()307 public String getTestObjectName() 308 { 309 return this.getClass().getName(); 310 } 311 } 312