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