merged tag ooo/DEV300_m102
[LibreOffice.git] / qadevOOo / runner / lib / MultiPropertyTest.java
bloba02f93c043478672c882485dbbf5dc7ffdcb4a64
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
27 package lib;
29 import com.sun.star.beans.Property;
30 import com.sun.star.beans.PropertyAttribute;
31 import com.sun.star.beans.PropertyVetoException;
32 import com.sun.star.beans.XPropertySet;
33 import com.sun.star.beans.XPropertySetInfo;
34 import com.sun.star.beans.UnknownPropertyException;
35 import com.sun.star.lang.XServiceInfo;
36 import com.sun.star.lang.IllegalArgumentException;
37 import com.sun.star.lang.WrappedTargetException;
38 import com.sun.star.uno.UnoRuntime;
40 import java.lang.reflect.Method;
42 import util.ValueChanger;
43 import util.ValueComparer;
44 import util.utils;
46 import com.sun.star.uno.Any;
47 import com.sun.star.uno.AnyConverter;
48 import com.sun.star.uno.Type;
50 /**
51 * MultiPropertyTest extends the functionality of MultiMethodTest to support
52 * services testing. Since, in most cases, service tests has one method testing
53 * most of its properties, the MultiPropertyTest provides unified version of
54 * the method: testProperty().
56 * <p>The testProperty() is called, when the MultiMethodTest's testing method
57 * is not found in the subclass. So, by defining such methods for properties
58 * the standard testing behavioutr can be changed.
60 * <p>The testing behaviour also can be changed by overriding compare(),
61 * getNewVAlue() or toString(Object) methods, or by extending PropertyTester
62 * class.
64 * @see MultiMethodTest
65 * @see #testProperty(String)
66 * @see #testProperty(String, Propertytester)
67 * @see #getNewValue
68 * @see #compare
69 * @see #toString(Object)
71 public class MultiPropertyTest extends MultiMethodTest
74 /**
75 * Contains a XPropertySet interface of the tested object. Is initialized
76 * in MultiMethodTest code.
78 public XPropertySet oObj;
79 protected boolean optionalService = false;
81 /**
82 * Overrides super.before() to check the service is supported by the object.
84 protected void before()
86 XServiceInfo xInfo = (XServiceInfo) UnoRuntime.queryInterface(
87 XServiceInfo.class, oObj);
89 optionalService = entry.isOptional;
91 String theService = getTestedClassName();
92 if (xInfo != null && !xInfo.supportsService(theService))
94 log.println("Service " + theService + " not available");
95 if (optionalService)
97 log.println("This is OK since it is optional");
99 else
101 Status.failed(theService + " is not supported");
107 * Overrides MultiMethodTest.invokeTestMethod(). If the test for the
108 * <code>meth</code> is not available (<code>meth</code> == <tt>null</tt>)
109 * calls testProperty method for the method. Otherwise calls
110 * super.invokeTestMethod().
112 * @see #MultiMethodTest.invokeTestMethod()
114 protected void invokeTestMethod(Method meth, String methName)
116 if (meth != null)
118 super.invokeTestMethod(meth, methName);
120 else
122 testProperty(methName);
127 * PropertyTester class defines how to test a property and defined
128 * to allow subclasses of MultiPropertyTest to change the testing
129 * behaviour more flexible, since the behaviour can be customized for
130 * each property separately, by providing subclass of PropertyTester
131 * and passing it to testProperty(String, PropertyTester method).
133 public class PropertyTester
137 * The method defines the whole process of testing propName
138 * property.
140 * <p>First, it checks if the property exists(it maybe optional).
141 * Then, a value to set the property with is calculated with
142 * getNewValue method. Normally, the new value is calculated
143 * based on old value, but subclasses can override the behaviour
144 * (for example, if old value is null) and specify their own value.
145 * Then the property is set with that new value and the result(
146 * it maybe an exception too, for example a PropertyVetoException)
147 * is checked with checkResult method.
149 * @param propName - the property to test.
150 * @result - adds the result of testing propName property to
151 * MultiMethodTest.tRes.
153 protected void testProperty(String propName)
155 XPropertySetInfo info = oObj.getPropertySetInfo();
157 if (info != null)
159 final boolean bHasProperty = info.hasPropertyByName(propName);
160 if (!bHasProperty)
162 if (isOptional(propName) || optionalService)
164 // skipping optional property test
165 log.println("Property '" + propName + "' is optional and not supported");
166 tRes.tested(propName, true);
167 return;
169 else
171 // cannot test the property
172 log.println("Tested XPropertySet does not contain'" + propName + "' property");
173 tRes.tested(propName, false);
174 return;
181 Object oldValue = oObj.getPropertyValue(propName);
183 if( (oldValue==null) || utils.isVoid(oldValue) )
185 // #i111560# method getNewValue() does not work with an empty oldValue
186 Property prop = info.getPropertyByName(propName);
187 if( (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0 )
189 // todo: implement a new test independent from method getNewValue()
190 log.println("changing initially empty MAYBEVOID properties is not supported by the test framework so far - skip test of property: " + propName);
191 tRes.tested(propName, true);
192 return;
194 else
196 log.println( "property '"+propName+"' is not set but is not MAYBEVOID");
197 tRes.tested(propName, false);
198 return;
202 Object newValue;
204 // trying to create new value
207 newValue = getNewValue(propName, oldValue);
209 catch (java.lang.IllegalArgumentException e)
211 // skipping test since new value is not available
212 Status.failed("Cannot create new value for '" + propName + " : " + e.getMessage());
213 return;
216 // for an exception thrown during setting new value
217 // to pass it to checkResult method
218 Exception exception = null;
222 log.println("try to set:");
223 log.println("old = " + toString(oldValue));
224 log.println("new = " + toString(newValue));
225 oObj.setPropertyValue(propName, newValue);
227 catch (IllegalArgumentException e)
229 exception = e;
231 catch (PropertyVetoException e)
233 exception = e;
235 catch (WrappedTargetException e)
237 exception = e;
239 catch (UnknownPropertyException e)
241 exception = e;
243 catch (RuntimeException e)
245 exception = e;
248 // getting result value
249 Object resValue = oObj.getPropertyValue(propName);
251 // checking results
252 checkResult(propName, oldValue, newValue, resValue, exception);
254 catch (Exception e)
256 log.println("Exception occured while testing property '" + propName + "'");
257 e.printStackTrace(log);
258 tRes.tested(propName, false);
263 * The method checks result of setting a new value to the
264 * property based o the following arguments:
265 * @propName - the property to test
266 * @oldValue - the old value of the property, before changing it.
267 * @newValue - the new value the property has been set with
268 * @resValue - the value of the property after having changed it
269 * @exception - if not null - the exception thrown by
270 * XPropertySet.setPropertyValue, else indicates
271 * normal method completion.
273 * <p>If the property is READ_ONLY, than either PropertyVetoException
274 * should be thrown or the value of property should not have changed
275 * (resValue is compared with oldValue with compare method).
277 * <p>If the property is not READ_ONLY, checks that the new value has
278 * been successfully set(resValue is compared with newValue with
279 * compare method).
281 * <p>If the exception is not null then(except the case of read-only
282 * property and PropertyVetoException above) it is rethrown to allow
283 * further catching it if needed.
285 * <p>Subclasses can override to change this behaviour.
287 protected void checkResult(String propName, Object oldValue,
288 Object newValue, Object resValue, Exception exception)
289 throws Exception
291 XPropertySetInfo info = oObj.getPropertySetInfo();
292 if (info == null)
294 log.println("Can't get XPropertySetInfo for property " + propName);
295 tRes.tested(propName, false);
296 return;
298 Property prop = info.getPropertyByName(propName);
300 short attr = prop.Attributes;
301 boolean readOnly = (prop.Attributes & PropertyAttribute.READONLY) != 0;
302 boolean maybeVoid = (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0;
303 //check get-set methods
304 if (maybeVoid)
306 log.println("Property " + propName + " is void");
308 if (readOnly)
310 log.println("Property " + propName + " is readOnly");
312 if (util.utils.isVoid(oldValue) && !maybeVoid)
314 log.println(propName + " is void, but it's not MAYBEVOID");
315 tRes.tested(propName, false);
317 else if (oldValue == null)
319 log.println(propName + " has null value, and therefore can't be changed");
320 tRes.tested(propName, true);
322 else if (readOnly)
324 // check if exception was thrown
325 if (exception != null)
327 if (exception instanceof PropertyVetoException)
329 // the change of read only prohibited - OK
330 log.println("Property is ReadOnly and wasn't changed");
331 log.println("Property '" + propName + "' OK");
332 tRes.tested(propName, true);
334 else if (exception instanceof IllegalArgumentException)
336 // the change of read only prohibited - OK
337 log.println("Property is ReadOnly and wasn't changed");
338 log.println("Property '" + propName + "' OK");
339 tRes.tested(propName, true);
341 else if (exception instanceof UnknownPropertyException)
343 // the change of read only prohibited - OK
344 log.println("Property is ReadOnly and wasn't changed");
345 log.println("Property '" + propName + "' OK");
346 tRes.tested(propName, true);
348 else if (exception instanceof RuntimeException)
350 // the change of read only prohibited - OK
351 log.println("Property is ReadOnly and wasn't changed");
352 log.println("Property '" + propName + "' OK");
353 tRes.tested(propName, true);
355 else
357 throw exception;
360 else
362 // if no exception - check that value
363 // has not changed
364 if (!compare(resValue, oldValue))
366 log.println("Read only property '" + propName + "' has changed");
369 if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
371 oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
373 // log.println("old = " + toString(oldValue));
374 // log.println("new = " + toString(newValue));
375 log.println("result = " + toString(resValue));
377 catch (com.sun.star.lang.IllegalArgumentException iae)
379 log.println("NOTIFY: this property needs further investigations.");
380 log.println("\t The type seems to be an Any with value of NULL.");
381 log.println("\t Maybe the property should get it's own test method.");
384 tRes.tested(propName, false);
386 else
388 log.println("Read only property '" + propName + "' hasn't changed");
389 log.println("Property '" + propName + "' OK");
390 tRes.tested(propName, true);
394 else
396 if (exception == null)
398 // if no exception thrown
399 // check that the new value is set
400 if ((!compare(resValue, newValue)) || (compare(resValue, oldValue)))
402 log.println("Value for '" + propName + "' hasn't changed as expected");
405 if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
407 oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
409 // log.println("old = " + toString(oldValue));
410 // log.println("new = " + toString(newValue));
411 log.println("result = " + toString(resValue));
413 catch (com.sun.star.lang.IllegalArgumentException iae)
415 log.println("NOTIFY: this property needs further investigations.");
416 log.println("\t The type seems to be an Any with value of NULL.");
417 log.println("\t Maybe the property should get it's own test method.");
419 if (resValue != null)
421 if ((!compare(resValue, oldValue)) || (!resValue.equals(oldValue)))
423 log.println("But it has changed.");
424 tRes.tested(propName, true);
426 else
428 tRes.tested(propName, false);
431 else
433 tRes.tested(propName, false);
435 //tRes.tested(propName, false);
437 else
439 log.println("Property '" + propName + "' OK");
442 if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
444 oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
446 // log.println("old = " + toString(oldValue));
447 // log.println("new = " + toString(newValue));
448 log.println("result = " + toString(resValue));
450 catch (com.sun.star.lang.IllegalArgumentException iae)
453 tRes.tested(propName, true);
456 else
458 throw exception;
464 * The method produces new value of the property from the oldValue.
465 * It returns the result of ValueChanger.changePValue method.
466 * Subclasses can override the method to return their own value,
467 * when the changePValue beahviour is not enough, for example,
468 * when oldValue is null.
470 protected Object getNewValue(String propName, Object oldValue)
471 throws java.lang.IllegalArgumentException
473 return ValueChanger.changePValue(oldValue);
477 * The method compares obj1 and obj2. It calls
478 * MultiPropertyTest.compare, but subclasses can override to change
479 * the behaviour, since normally compare calls Object.equals method
480 * which is not apropriate in some cases(e.g., structs with equals
481 * not overridden).
483 protected boolean compare(Object obj1, Object obj2)
485 return callCompare(obj1, obj2);
489 * The method returns a String representation of the obj. It calls
490 * MultipropertyTest.toString(Object), but subclasses can override
491 * to change the behaviour.
493 protected String toString(Object obj)
495 return callToString(obj);
500 * Extension for <code>PropertyTester</code> which switches two
501 * different values. <code>getNewValue()</code> method of this
502 * class returns one of these two values depending on the
503 * old value, so new value is not equal to old value.
505 public class PropertyValueSwitcher extends PropertyTester
508 Object val1 = null;
509 Object val2 = null;
512 * Constructs a property tester with two different values
513 * specified as parameters.
515 * @param val1 Not <code>null</code> value for the property
516 * tested.
517 * @param val1 Not <code>null</code> value for the property
518 * tested which differs from the first value.
520 public PropertyValueSwitcher(Object val1, Object val2)
522 this.val1 = val1;
523 this.val2 = val2;
527 * Overriden method of <code>PropertyTester</code> which
528 * retruns new value from two values specified.
530 * @return The second value if old value is equal to the first
531 * one, the first value otherwise.
533 protected Object getNewValue(String propName, Object old)
535 if (ValueComparer.equalValue(val1, old))
537 return val2;
539 else
541 return val1;
547 * The method performs testing of propName property using propTester.
549 protected void testProperty(String propName, PropertyTester propTester)
551 propTester.testProperty(propName);
555 * The method performs testing of propName property. It uses PropertyTester
556 * instance for testing.
558 protected void testProperty(String propName)
560 testProperty(propName, new PropertyTester());
564 * Tests the property using <code>PropertyValueSwitcher</code>
565 * tester and two values for this property.
567 * @see #PropertyValueSwitcher
569 protected void testProperty(String propName, Object val1, Object val2)
571 testProperty(propName, new PropertyValueSwitcher(val1, val2));
575 * The method just calls compare. This is a workaround to CodeWarrior's
576 * compiler bug.
578 private boolean callCompare(Object obj1, Object obj2)
580 return compare(obj1, obj2);
584 * Compares two object. In the implementation calls obj1.equals(obj2).
586 protected boolean compare(Object obj1, Object obj2)
588 return ValueComparer.equalValue(obj1, obj2);
592 * The method just calls toString. This is a workaround to
593 * CodeWarrior's compiler bug.
595 private String callToString(Object obj)
597 return toString(obj);
601 * Gets string representation of the obj. In the implementation
602 * returns obj.toString().
604 protected String toString(Object obj)
606 return obj == null ? "null" : obj.toString();