bump product version to 4.1.6.2
[LibreOffice.git] / qadevOOo / runner / lib / MultiMethodTest.java
blobdd467af2c8b024663e1f12039de06735f72ca119
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 package lib;
20 import java.io.PrintWriter;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.ArrayList;
26 import share.DescEntry;
27 import stats.Summarizer;
29 import com.sun.star.uno.UnoRuntime;
31 /**
32 * The class supports method based interface tests development.
34 * <p>There are some points that should be fulfilled in a subclass to work
35 * correctly in the multi-method framework:
37 * 1. each subclass schould define a public field named oObj of type tested
38 * by the subclass, e.g. 'public XText oObj;'. That field will be initialized
39 * by the MultiMethodTest code with the instance of the interface to test.
40 * In a case of service testing the field type should be XPropertySet.
42 * 2. for the test of each method of the tested interface(or a property in the
43 * case of service testing) should be method with the following signature
44 * provided: 'public void _<method name>()', e.g. 'public void _getText()'.
45 * The methods will be called by MultiMethodText code using reflection API
46 * for each method in the interface description.
48 * 3. to set status for a call 'tRes.tested(String method,
49 * boolean result)' should be used. For example 'tRes.tested("getText()",
50 * true)'. Also 'tRes.assert(String assertion, boolean result)' call can
51 * be used. Note, that one can call the methods not neccesarily from the
52 * test for the tested method, but from other method tests too (in the
53 * MultiMethodTest subclass). See also TestResult and MultiMethodTest.tRes
54 * documentation.
56 * 4. the before() and after() methods can be overriden to perform some
57 * actions, accordingly, before and after calling the test methods.
59 * 5. besides tRes, there are some fields initialized in the MultiMethodTest,
60 * that can be used for implementing tests:
62 * - tEnv contains the environment tested
63 * - tParam contains parameters of the test
64 * - log a writer to log information about the test
66 * @see TestResult
68 public class MultiMethodTest
71 /**
72 * Contains the TestEnvironment being tested, to allow for tests to access
73 * it.
75 protected TestEnvironment tEnv;
76 /**
77 * Contains the TestParameters for the tests, to allow for tests to access
78 * it.
80 protected TestParameters tParam;
81 /**
82 * Contains the Description for the test
83 * it.
85 protected DescEntry entry;
86 /**
87 * Contains a writer to log an information about the interface testing, to
88 * allows for tests to access it.
90 protected PrintWriter log;
91 /**
92 * Contains the TestResult instance for the interface test to collect
93 * information about methods test.
95 protected TestResult tRes;
96 /**
97 * Contains names of the methods have been already called
99 private ArrayList<String> methCalled = new ArrayList<String>(10);
102 * Disposes the test environment, which was corrupted by the test.
104 * @param tEnv the environment to dispose
106 public void disposeEnvironment(TestEnvironment tEnv)
108 disposeEnvironment();
112 * Disposes the current test environment, which was corrupted by the test.
114 * @see #disposeEnvironment(TestEnvironment)
116 public void disposeEnvironment()
118 tEnv.dispose();
119 TestCase tCase = tEnv.getTestCase();
120 tCase.disposeTestEnvironment(tEnv, tParam);
124 * Runs the interface test: its method tests. First, it initializes some
125 * of MultiMethodTest fields, like tRes, log, tEnv, etc. Then, it queries
126 * the tested interface and initializes 'oObj' field (defined in a
127 * subclass). Before calling method tests, before() method calles to allow
128 * initialization of s stuff before testing. Then, the method tests are
129 * called. After them, after() method is called, to allow cleaning up the
130 * stuff initialized in before() and test methods.
132 * @param entry the interface test state
133 * @param tEnv the environment to test
134 * @param tParam the parameters of the test
136 * @see #before
137 * @see #after
139 public TestResult run(DescEntry entry, TestEnvironment tEnv, TestParameters tParam)
142 log = (PrintWriter) entry.Logger;
144 this.tEnv = tEnv;
145 this.tParam = tParam;
146 // this.log = log;
147 this.entry = entry;
148 this.tRes = new TestResult();
149 Class<?> testedClass;
151 // Some fake code for a self test.
152 // For normal test we must not be a "ifc.qadevooo._SelfTest"
153 if (! ("ifc.qadevooo._SelfTest").equals(entry.entryName))
155 getInterfaceName();
156 // System.out.println("checking : " + ifcName);
157 System.out.print("checking: [" + entry.longName + "]");
159 // defining a name of the class corresponding to the tested interface
160 // or service
161 String testedClassName;
163 testedClassName = getTestedClassName();
165 if (entry.EntryType.equals("service"))
167 testedClassName = "com.sun.star.beans.XPropertySet";
172 testedClass = Class.forName(testedClassName);
174 catch (ClassNotFoundException cnfE)
176 System.out.println();
177 cnfE.printStackTrace(log);
178 log.println("could not find a class : " + getTestedClassName());
179 return null;
181 System.out.println(" is iface: [" + testedClassName + "] testcode: [" + entry.entryName + "]");
183 tEnv.getTestObject();
184 Object oObj = UnoRuntime.queryInterface(testedClass, tEnv.getTestObject());
186 if (oObj == null)
188 if (entry.isOptional)
190 Summarizer.summarizeDown(entry, "Not supported but optional.OK");
192 else
194 Summarizer.summarizeDown(entry, "queryInterface returned null.FAILED");
195 entry.ErrorMsg = "queryInterface returned null";
196 entry.hasErrorMsg = true;
199 return null;
202 //setting the field oObj
203 setField("oObj", oObj);
206 // to perform some stuff before all method tests
209 before();
211 catch (Exception e)
213 e.printStackTrace();
214 setSubStates(e.toString());
215 return tRes;
218 // executing methods tests
219 for (int i = 0; i < entry.SubEntryCount; i++)
221 DescEntry aSubEntry = entry.SubEntries[i];
224 final String sEntryName = aSubEntry.entryName;
225 executeMethod(sEntryName);
227 catch (Exception e)
229 log.println("Exception while checking: " + aSubEntry.entryName + " : " + e.getMessage());
233 // to perform some stuff after all method tests
236 after();
238 catch (Exception e)
242 return tRes;
246 * Is called before calling method tests, but after initialization.
247 * Subclasses may override to perform actions before method tests.
249 protected void before()
254 * Is called after calling method tests. Subclasses may override
255 * to perform actions after method tests.
257 protected void after()
262 * @return the name of the interface or the service tested.
264 protected String getTestedClassName()
266 String clsName = this.getClass().getName();
268 int firstDot = clsName.indexOf('.');
269 int lastDot = clsName.lastIndexOf('.');
271 String append = "com.sun.star.";
273 if (entry.longName.indexOf("::drafts::com::") > -1)
275 append = "drafts.com.sun.star.";
278 return append + clsName.substring(firstDot + 1, lastDot + 1) + clsName.substring(lastDot + 2);
282 * Sets a method status.
284 * @param methName the method name to set status
285 * @param methStatus the status to set to the method
287 protected void setStatus(String methName, Status methStatus)
289 tRes.tested(methName, methStatus);
293 * sets the substates
295 protected void setSubStates(String msg)
297 for (int k = 0; k < entry.SubEntryCount; k++)
299 entry.SubEntries[k].hasErrorMsg = true;
300 entry.SubEntries[k].ErrorMsg = msg;
301 if (entry.SubEntries[k].State.equals("UNKNOWN"))
303 entry.SubEntries[k].State = msg;
310 * Checks if the <code>method</code> is optional in the service.
312 protected boolean isOptional(String _method)
314 for (int k = 0; k < entry.SubEntryCount; k++)
316 final String sName = entry.SubEntries[k].entryName;
317 if (sName.equals(_method))
319 final boolean bIsOptional = entry.SubEntries[k].isOptional;
320 return bIsOptional;
323 return false;
327 * Checks if the <code>method</code> test has been already called.
329 protected boolean isCalled(String method)
331 return methCalled.contains(method);
335 * Calling of the method indicates that the <code>method</code> test should
336 * be called. The method checks this and if it is not called, calls it.
337 * If the method is failed or skipped, it throws StatusException.
339 protected void requiredMethod(String method)
341 log.println("starting required method: " + method);
342 executeMethod(method);
343 Status mtStatus = tRes.getStatusFor(method);
345 if (mtStatus != null && (!mtStatus.isPassed() || mtStatus.isFailed()))
347 log.println("! Required method " + method + " failed");
348 throw new StatusException(mtStatus);
353 * Checks if the <code>method</code> was called, and if not, call it.
354 * On contrary to requiredMethod(), he method doesn't check its status.
356 protected void executeMethod(String method)
358 if (!isCalled(method))
360 log.println("Execute: " + method);
361 callMethod(method);
362 log.println(method + ": " + tRes.getStatusFor(method));
363 log.println();
368 * Just calls the <code>method</code> test.
370 protected void callMethod(String method)
372 methCalled.add(method);
373 invokeTestMethod(getMethodFor(method), method);
377 * Invokes a test method of the subclass using reflection API. Handles
378 * the method results and sets its status.
380 * @param meth the subclass' method to invoke
381 * @param methName the name of the method
383 protected void invokeTestMethod(Method meth, String methName)
385 if (meth == null)
387 setStatus(methName, Status.skipped(false));
389 else
391 Status stat;
395 meth.invoke(this, new Object[0]);
396 return;
398 catch (InvocationTargetException itE)
400 Throwable t = itE.getTargetException();
402 if (t instanceof StatusException)
404 stat = ((StatusException) t).getStatus();
406 else
408 t.printStackTrace(log);
409 stat = Status.exception(t);
412 catch (IllegalAccessException iaE)
414 iaE.printStackTrace(log);
415 stat = Status.exception(iaE);
417 catch (IllegalArgumentException iaE)
419 iaE.printStackTrace(log);
420 stat = Status.exception(iaE);
422 catch (ClassCastException ccE)
424 ccE.printStackTrace(log);
425 stat = Status.exception(ccE);
428 setStatus(methName, stat);
433 * Finds a testing method for the <code>method</code> of the interface.
435 * @return the testing method, if found, <tt>null</tt> otherwise
437 protected Method getMethodFor(String method)
439 String mName = "_" + method;
441 if (mName.endsWith("()"))
443 mName = mName.substring(0, mName.length() - 2);
446 final Class<?>[] paramTypes = new Class[0];
450 return this.getClass().getDeclaredMethod(mName, paramTypes);
452 catch (NoSuchMethodException nsmE)
454 return null;
459 * @return the name of the interface tested
461 public String getInterfaceName()
463 String clName = this.getClass().getName();
464 return clName.substring(clName.lastIndexOf('.') + 1);
468 * Initializes <code>fieldName</code> of the subclass with
469 * <code>value</code>.
471 * @return Status describing the result of the operation.
473 protected Status setField(String fieldName, Object value)
475 Field objField;
479 objField = this.getClass().getField(fieldName);
481 catch (NoSuchFieldException nsfE)
483 return Status.exception(nsfE);
488 objField.set(this, value);
489 return Status.passed(true);
491 catch (IllegalArgumentException iaE)
493 return Status.exception(iaE);
495 catch (IllegalAccessException iaE)
497 return Status.exception(iaE);