bump product version to 4.2.0.1
[LibreOffice.git] / qadevOOo / runner / lib / MultiPropertyTest.java
blobc52a9d84f71cf912d9e0e8452a00a2e99eab0adc
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 com.sun.star.beans.Property;
21 import com.sun.star.beans.PropertyAttribute;
22 import com.sun.star.beans.PropertyVetoException;
23 import com.sun.star.beans.XPropertySet;
24 import com.sun.star.beans.XPropertySetInfo;
25 import com.sun.star.beans.UnknownPropertyException;
26 import com.sun.star.lang.XServiceInfo;
27 import com.sun.star.lang.IllegalArgumentException;
28 import com.sun.star.lang.WrappedTargetException;
29 import com.sun.star.uno.UnoRuntime;
31 import java.lang.reflect.Method;
33 import util.ValueChanger;
34 import util.ValueComparer;
35 import util.utils;
37 import com.sun.star.uno.Any;
38 import com.sun.star.uno.AnyConverter;
39 import com.sun.star.uno.Type;
41 /**
42 * MultiPropertyTest extends the functionality of MultiMethodTest to support
43 * services testing. Since, in most cases, service tests has one method testing
44 * most of its properties, the MultiPropertyTest provides unified version of
45 * the method: testProperty().
47 * <p>The testProperty() is called, when the MultiMethodTest's testing method
48 * is not found in the subclass. So, by defining such methods for properties
49 * the standard testing behavioutr can be changed.
51 * <p>The testing behaviour also can be changed by overriding compare(),
52 * getNewVAlue() or toString(Object) methods, or by extending PropertyTester
53 * class.
55 * @see MultiMethodTest
56 * @see #testProperty(String)
57 * @see #testProperty(String, PropertyTester)
58 * @see #getNewValue
59 * @see #compare
60 * @see #toString(Object)
62 public class MultiPropertyTest extends MultiMethodTest
65 /**
66 * Contains a XPropertySet interface of the tested object. Is initialized
67 * in MultiMethodTest code.
69 public XPropertySet oObj;
70 protected boolean optionalService = false;
72 /**
73 * Overrides super.before() to check the service is supported by the object.
75 protected void before()
77 XServiceInfo xInfo = UnoRuntime.queryInterface(
78 XServiceInfo.class, oObj);
80 optionalService = entry.isOptional;
82 String theService = getTestedClassName();
83 if (xInfo != null && !xInfo.supportsService(theService))
85 log.println("Service " + theService + " not available");
86 if (optionalService)
88 log.println("This is OK since it is optional");
90 else
92 Status.failed(theService + " is not supported");
97 /**
98 * Overrides MultiMethodTest.invokeTestMethod(). If the test for the
99 * <code>meth</code> is not available (<code>meth</code> == <tt>null</tt>)
100 * calls testProperty method for the method. Otherwise calls
101 * super.invokeTestMethod().
103 * @see MultiMethodTest#invokeTestMethod
105 protected void invokeTestMethod(Method meth, String methName)
107 if (meth != null)
109 super.invokeTestMethod(meth, methName);
111 else
113 testProperty(methName);
118 * PropertyTester class defines how to test a property and defined
119 * to allow subclasses of MultiPropertyTest to change the testing
120 * behaviour more flexible, since the behaviour can be customized for
121 * each property separately, by providing subclass of PropertyTester
122 * and passing it to testProperty(String, PropertyTester method).
124 public class PropertyTester
128 * The method defines the whole process of testing propName
129 * property.
131 * <p>First, it checks if the property exists(it maybe optional).
132 * Then, a value to set the property with is calculated with
133 * getNewValue method. Normally, the new value is calculated
134 * based on old value, but subclasses can override the behaviour
135 * (for example, if old value is null) and specify their own value.
136 * Then the property is set with that new value and the result(
137 * it maybe an exception too, for example a PropertyVetoException)
138 * is checked with checkResult method.
140 * @param propName - the property to test.
141 * @result - adds the result of testing propName property to
142 * MultiMethodTest.tRes.
144 protected void testProperty(String propName)
146 XPropertySetInfo info = oObj.getPropertySetInfo();
148 if (info != null)
150 final boolean bHasProperty = info.hasPropertyByName(propName);
151 if (!bHasProperty)
153 if (isOptional(propName) || optionalService)
155 // skipping optional property test
156 log.println("Property '" + propName + "' is optional and not supported");
157 tRes.tested(propName, true);
158 return;
160 else
162 // cannot test the property
163 log.println("Tested XPropertySet does not contain'" + propName + "' property");
164 tRes.tested(propName, false);
165 return;
172 Object oldValue = oObj.getPropertyValue(propName);
174 if( (oldValue==null) || utils.isVoid(oldValue) )
176 // #i111560# method getNewValue() does not work with an empty oldValue
177 Property prop = info.getPropertyByName(propName);
178 if( (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0 )
180 // todo: implement a new test independent from method getNewValue()
181 log.println("changing initially empty MAYBEVOID properties is not supported by the test framework so far - skip test of property: " + propName);
182 tRes.tested(propName, true);
183 return;
185 else
187 log.println( "property '"+propName+"' is not set but is not MAYBEVOID");
188 tRes.tested(propName, false);
189 return;
193 Object newValue;
195 // trying to create new value
198 newValue = getNewValue(propName, oldValue);
200 catch (java.lang.IllegalArgumentException e)
202 // skipping test since new value is not available
203 Status.failed("Cannot create new value for '" + propName + " : " + e.getMessage());
204 return;
207 // for an exception thrown during setting new value
208 // to pass it to checkResult method
209 Exception exception = null;
213 log.println("try to set:");
214 log.println("old = " + toString(oldValue));
215 log.println("new = " + toString(newValue));
216 oObj.setPropertyValue(propName, newValue);
218 catch (IllegalArgumentException e)
220 exception = e;
222 catch (PropertyVetoException e)
224 exception = e;
226 catch (WrappedTargetException e)
228 exception = e;
230 catch (UnknownPropertyException e)
232 exception = e;
234 catch (RuntimeException e)
236 exception = e;
239 // getting result value
240 Object resValue = oObj.getPropertyValue(propName);
242 // checking results
243 checkResult(propName, oldValue, newValue, resValue, exception);
245 catch (Exception e)
247 log.println("Exception occurred while testing property '" + propName + "'");
248 e.printStackTrace(log);
249 tRes.tested(propName, false);
254 * The method checks result of setting a new value to the
255 * property based o the following arguments:
256 * @param propName - the property to test
257 * @param oldValue - the old value of the property, before changing it.
258 * @param newValue - the new value the property has been set with
259 * @param resValue - the value of the property after having changed it
260 * @param exception - if not null - the exception thrown by
261 * XPropertySet.setPropertyValue, else indicates
262 * normal method completion.
264 * <p>If the property is READ_ONLY, than either PropertyVetoException
265 * should be thrown or the value of property should not have changed
266 * (resValue is compared with oldValue with compare method).
268 * <p>If the property is not READ_ONLY, checks that the new value has
269 * been successfully set(resValue is compared with newValue with
270 * compare method).
272 * <p>If the exception is not null then(except the case of read-only
273 * property and PropertyVetoException above) it is rethrown to allow
274 * further catching it if needed.
276 * <p>Subclasses can override to change this behaviour.
278 protected void checkResult(String propName, Object oldValue,
279 Object newValue, Object resValue, Exception exception)
280 throws Exception
282 XPropertySetInfo info = oObj.getPropertySetInfo();
283 if (info == null)
285 log.println("Can't get XPropertySetInfo for property " + propName);
286 tRes.tested(propName, false);
287 return;
289 Property prop = info.getPropertyByName(propName);
291 boolean readOnly = (prop.Attributes & PropertyAttribute.READONLY) != 0;
292 boolean maybeVoid = (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0;
293 //check get-set methods
294 if (maybeVoid)
296 log.println("Property " + propName + " is void");
298 if (readOnly)
300 log.println("Property " + propName + " is readOnly");
302 if (util.utils.isVoid(oldValue) && !maybeVoid)
304 log.println(propName + " is void, but it's not MAYBEVOID");
305 tRes.tested(propName, false);
307 else if (oldValue == null)
309 log.println(propName + " has null value, and therefore can't be changed");
310 tRes.tested(propName, true);
312 else if (readOnly)
314 // check if exception was thrown
315 if (exception != null)
317 if (exception instanceof PropertyVetoException)
319 // the change of read only prohibited - OK
320 log.println("Property is ReadOnly and wasn't changed");
321 log.println("Property '" + propName + "' OK");
322 tRes.tested(propName, true);
324 else if (exception instanceof IllegalArgumentException)
326 // the change of read only prohibited - OK
327 log.println("Property is ReadOnly and wasn't changed");
328 log.println("Property '" + propName + "' OK");
329 tRes.tested(propName, true);
331 else if (exception instanceof UnknownPropertyException)
333 // the change of read only prohibited - OK
334 log.println("Property is ReadOnly and wasn't changed");
335 log.println("Property '" + propName + "' OK");
336 tRes.tested(propName, true);
338 else if (exception instanceof RuntimeException)
340 // the change of read only prohibited - OK
341 log.println("Property is ReadOnly and wasn't changed");
342 log.println("Property '" + propName + "' OK");
343 tRes.tested(propName, true);
345 else
347 throw exception;
350 else
352 // if no exception - check that value
353 // has not changed
354 if (!compare(resValue, oldValue))
356 log.println("Read only property '" + propName + "' has changed");
359 if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
361 oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
363 // log.println("old = " + toString(oldValue));
364 // log.println("new = " + toString(newValue));
365 log.println("result = " + toString(resValue));
367 catch (com.sun.star.lang.IllegalArgumentException iae)
369 log.println("NOTIFY: this property needs further investigations.");
370 log.println("\t The type seems to be an Any with value of NULL.");
371 log.println("\t Maybe the property should get it's own test method.");
374 tRes.tested(propName, false);
376 else
378 log.println("Read only property '" + propName + "' hasn't changed");
379 log.println("Property '" + propName + "' OK");
380 tRes.tested(propName, true);
384 else
386 if (exception == null)
388 // if no exception thrown
389 // check that the new value is set
390 if ((!compare(resValue, newValue)) || (compare(resValue, oldValue)))
392 log.println("Value for '" + propName + "' hasn't changed as expected");
395 if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
397 oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
399 // log.println("old = " + toString(oldValue));
400 // log.println("new = " + toString(newValue));
401 log.println("result = " + toString(resValue));
403 catch (com.sun.star.lang.IllegalArgumentException iae)
405 log.println("NOTIFY: this property needs further investigations.");
406 log.println("\t The type seems to be an Any with value of NULL.");
407 log.println("\t Maybe the property should get it's own test method.");
409 if (resValue != null)
411 if ((!compare(resValue, oldValue)) || (!resValue.equals(oldValue)))
413 log.println("But it has changed.");
414 tRes.tested(propName, true);
416 else
418 tRes.tested(propName, false);
421 else
423 tRes.tested(propName, false);
425 //tRes.tested(propName, false);
427 else
429 log.println("Property '" + propName + "' OK");
432 if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
434 oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
436 // log.println("old = " + toString(oldValue));
437 // log.println("new = " + toString(newValue));
438 log.println("result = " + toString(resValue));
440 catch (com.sun.star.lang.IllegalArgumentException iae)
443 tRes.tested(propName, true);
446 else
448 throw exception;
454 * The method produces new value of the property from the oldValue.
455 * It returns the result of ValueChanger.changePValue method.
456 * Subclasses can override the method to return their own value,
457 * when the changePValue beahviour is not enough, for example,
458 * when oldValue is null.
460 protected Object getNewValue(String propName, Object oldValue)
461 throws java.lang.IllegalArgumentException
463 return ValueChanger.changePValue(oldValue);
467 * The method compares obj1 and obj2. It calls
468 * MultiPropertyTest.compare, but subclasses can override to change
469 * the behaviour, since normally compare calls Object.equals method
470 * which is not apropriate in some cases(e.g., structs with equals
471 * not overridden).
473 protected boolean compare(Object obj1, Object obj2)
475 return callCompare(obj1, obj2);
479 * The method returns a String representation of the obj. It calls
480 * MultipropertyTest.toString(Object), but subclasses can override
481 * to change the behaviour.
483 protected String toString(Object obj)
485 return callToString(obj);
490 * Extension for <code>PropertyTester</code> which switches two
491 * different values. <code>getNewValue()</code> method of this
492 * class returns one of these two values depending on the
493 * old value, so new value is not equal to old value.
495 public class PropertyValueSwitcher extends PropertyTester
498 Object val1 = null;
499 Object val2 = null;
502 * Constructs a property tester with two different values
503 * specified as parameters.
505 * @param val1 Not <code>null</code> value for the property
506 * tested.
507 * @param val2 Not <code>null</code> value for the property
508 * tested which differs from the first value.
510 public PropertyValueSwitcher(Object val1, Object val2)
512 this.val1 = val1;
513 this.val2 = val2;
517 * Overriden method of <code>PropertyTester</code> which
518 * retruns new value from two values specified.
520 * @return The second value if old value is equal to the first
521 * one, the first value otherwise.
523 protected Object getNewValue(String propName, Object old)
525 if (ValueComparer.equalValue(val1, old))
527 return val2;
529 else
531 return val1;
537 * The method performs testing of propName property using propTester.
539 protected void testProperty(String propName, PropertyTester propTester)
541 propTester.testProperty(propName);
545 * The method performs testing of propName property. It uses PropertyTester
546 * instance for testing.
548 protected void testProperty(String propName)
550 testProperty(propName, new PropertyTester());
554 * Tests the property using <code>PropertyValueSwitcher</code>
555 * tester and two values for this property.
557 * @see PropertyValueSwitcher
559 protected void testProperty(String propName, Object val1, Object val2)
561 testProperty(propName, new PropertyValueSwitcher(val1, val2));
565 * The method just calls compare. This is a workaround to CodeWarrior's
566 * compiler bug.
568 private boolean callCompare(Object obj1, Object obj2)
570 return compare(obj1, obj2);
574 * Compares two object. In the implementation calls obj1.equals(obj2).
576 protected boolean compare(Object obj1, Object obj2)
578 return ValueComparer.equalValue(obj1, obj2);
582 * The method just calls toString. This is a workaround to
583 * CodeWarrior's compiler bug.
585 private String callToString(Object obj)
587 return toString(obj);
591 * Gets string representation of the obj. In the implementation
592 * returns obj.toString().
594 protected String toString(Object obj)
596 return obj == null ? "null" : obj.toString();