| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| package complexlib; |
| |
| import java.lang.reflect.Method; |
| import share.DescEntry; |
| import lib.TestParameters; |
| import lib.StatusException; |
| import share.LogWriter; |
| import share.ComplexTest; |
| import java.io.PrintWriter; |
| |
| /** |
| * Base class for all complex tests. |
| */ |
| public abstract class ComplexTestCase extends Assurance implements ComplexTest |
| { |
| |
| /** The test parameters **/ |
| protected static TestParameters param = null; |
| /** Log writer **/ |
| protected static LogWriter log = null; |
| /** |
| * The method name which will be written into f.e. the data base |
| **/ |
| protected String mTestMethodName = null; |
| /** Maximal time one method is allowed to execute |
| * Can be set with parameter 'ThreadTimeOut' |
| **/ |
| protected int m_nThreadTimeOut = 0; |
| /** Continue a test even if it did fail **/ |
| // public static final boolean CONTINUE = true; |
| |
| /** End a test if it did fail **/ |
| public static final boolean BREAK = true; |
| |
| private boolean m_bBeforeCalled; |
| |
| /** |
| * is called before the real test starts |
| */ |
| private void before() |
| { |
| try |
| { |
| Method before = this.getClass().getMethod("before", new Class[] {} ); |
| before.invoke(this, new Object[] {} ); |
| |
| // beforeWorked = false; |
| m_bBeforeCalled = true; |
| } |
| catch (java.lang.NoSuchMethodException e) |
| { |
| // simply ignore |
| int dummy = 0; |
| m_bBeforeCalled = true; |
| } |
| catch (java.lang.IllegalAccessException e) |
| { |
| log.println("Cannot access the 'before()' method, although it" + " is there. Is this ok?"); |
| } |
| catch (java.lang.reflect.InvocationTargetException e) |
| { |
| Throwable t = e.getTargetException(); |
| if (!(t instanceof RuntimeException) || state) |
| { |
| log.println(t.toString()); |
| if (message == null) |
| { |
| message = "Exception in before() method.\n\r" + t.getMessage(); |
| } |
| state = false; |
| t.printStackTrace((PrintWriter) log); |
| } |
| } |
| |
| } |
| |
| /** Description entry **/ |
| // protected DescEntry subEntry = null; |
| |
| private void test_method(DescEntry _entry) |
| { |
| |
| m_nThreadTimeOut = param.getInt("ThreadTimeOut"); |
| if (m_nThreadTimeOut == 0) |
| { |
| m_nThreadTimeOut = 300000; |
| } |
| |
| for (int i = 0; i < _entry.SubEntries.length; i++) |
| { |
| |
| DescEntry subEntry = _entry.SubEntries[i]; |
| if (m_bBeforeCalled) |
| { |
| state = true; |
| message = ""; |
| } |
| else |
| { |
| // set all test methods on failed, if 'before()' did not work. |
| subEntry.State = message; |
| subEntry.hasErrorMsg = true; |
| subEntry.ErrorMsg = message; |
| continue; |
| } |
| Method testMethod = null; |
| try |
| { |
| String entryName = subEntry.entryName; |
| Object[] parameter = null; |
| |
| if (entryName.indexOf("(") != -1) |
| { |
| String sParameter = (entryName.substring(entryName.indexOf("(") + 1, entryName.indexOf(")"))); |
| mTestMethodName = entryName; |
| parameter = new String[] { sParameter }; |
| entryName = entryName.substring(0, entryName.indexOf("(")); |
| testMethod = this.getClass().getMethod(entryName, new Class[] { String.class }); |
| } |
| else |
| { |
| testMethod = this.getClass().getMethod(entryName, new Class[] {} ); |
| mTestMethodName = entryName; |
| } |
| |
| MethodThread th = new MethodThread(testMethod, this, parameter, (java.io.PrintWriter) log); |
| log.println("Starting " + mTestMethodName); |
| th.start(); |
| |
| try |
| { |
| // some tests are very dynamic in its exceution time so that |
| // a threadTimeOut fials. In this cases the logging mechanisim |
| // is a useful way to detect that a office respective a test |
| // is running and not death. |
| // But way ThreadTimeOut? |
| // There exeitsts a complex test which uses no office. Therefore |
| // a logging mechanisim to detect a stalled test. |
| int lastPing = -1; |
| int newPing = 0; |
| |
| int sleepingStep = 1000; |
| int factor = 0; |
| |
| while (th.isAlive() && (lastPing != newPing || factor * sleepingStep < m_nThreadTimeOut)) |
| { |
| Thread.sleep(sleepingStep); |
| factor++; |
| // if a test starts the office itself it the watcher is a |
| // new one. |
| share.Watcher ow = (share.Watcher) param.get("Watcher"); |
| if (ow != null) |
| { |
| lastPing = newPing; |
| newPing = ow.getPing(); |
| //System.out.println("lastPing: '" + lastPing + "' newPing '" + newPing + "'"); |
| factor = 0; |
| } |
| } |
| } |
| catch (InterruptedException e) |
| { |
| } |
| if (th.isAlive()) |
| { |
| log.println("Destroy " + mTestMethodName); |
| th.destroy(); |
| subEntry.State = "Test did sleep for " + (m_nThreadTimeOut / 1000) + " seconds and has been killed!"; |
| subEntry.hasErrorMsg = true; |
| subEntry.ErrorMsg = subEntry.State; |
| continue; |
| } |
| else |
| { |
| log.println("Finished " + mTestMethodName); |
| if (th.hasErrorMessage()) |
| { |
| subEntry.State = th.getErrorMessage(); |
| subEntry.hasErrorMsg = true; |
| subEntry.ErrorMsg = subEntry.State; |
| continue; |
| } |
| } |
| } |
| catch (java.lang.Exception e) |
| { |
| log.println(e.getClass().getName()); |
| String msg = e.getMessage(); |
| log.println("Message: " + msg); |
| e.printStackTrace((PrintWriter) log); |
| subEntry.State = "SKIPPED.FAILED"; |
| subEntry.hasErrorMsg = true; |
| subEntry.ErrorMsg = (msg == null ? "" : msg); |
| continue; |
| } |
| subEntry.State = (state ? "PASSED.OK" : message); |
| subEntry.hasErrorMsg = !state; |
| subEntry.ErrorMsg = message; |
| } |
| } |
| |
| /** |
| * after() is called after the test is done |
| */ |
| private void after() |
| { |
| if (m_bBeforeCalled) |
| { |
| // the after() method |
| try |
| { |
| Method after = this.getClass().getMethod("after", new Class[] {}); |
| after.invoke(this, new Object[] {} ); |
| } |
| catch (java.lang.NoSuchMethodException e) |
| { |
| // simply ignore |
| } |
| catch (java.lang.IllegalAccessException e) |
| { |
| // simply ignore |
| } |
| catch (java.lang.reflect.InvocationTargetException e) |
| { |
| Throwable t = e.getTargetException(); |
| if (!(t instanceof StatusException)) |
| { |
| log.println(t.toString()); |
| if (message == null) |
| { |
| message = "Exception in after() method.\n\r" + t.getMessage(); |
| } |
| else |
| { |
| message += "Exception in \'after()\' method.\n\r" + t.getMessage(); |
| } |
| log.println("Message: " + message); |
| t.printStackTrace((PrintWriter) log); |
| } |
| } |
| } |
| |
| } |
| |
| |
| |
| /** |
| * Call test. It is expected, that an environment is |
| * given to this test. |
| * |
| * @param entry The name of the test method that should be called. |
| * @param environment The environment for the test. |
| */ |
| public void executeMethods(DescEntry entry, TestParameters environment) |
| { |
| m_bBeforeCalled = false; |
| |
| // get the environment |
| param = environment; |
| log = entry.Logger; |
| |
| |
| // start with the before() method |
| before(); |
| |
| //executeMethodTests |
| test_method(entry); |
| |
| // cleanup |
| after(); |
| } |
| |
| |
| /** |
| * Implement this method in the Complex test. |
| * @return All test method names. |
| */ |
| public abstract String[] getTestMethodNames(); |
| |
| /** |
| * Return a name for the test or tested object. |
| * Override to give an own name. |
| * @return As default, the name of this class. |
| */ |
| public String getTestObjectName() |
| { |
| return this.getClass().getName(); |
| } |
| } |