summaryrefslogtreecommitdiff
path: root/qadevOOo/runner/lib/MultiPropertyTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'qadevOOo/runner/lib/MultiPropertyTest.java')
-rw-r--r--qadevOOo/runner/lib/MultiPropertyTest.java608
1 files changed, 608 insertions, 0 deletions
diff --git a/qadevOOo/runner/lib/MultiPropertyTest.java b/qadevOOo/runner/lib/MultiPropertyTest.java
new file mode 100644
index 000000000000..a02f93c04347
--- /dev/null
+++ b/qadevOOo/runner/lib/MultiPropertyTest.java
@@ -0,0 +1,608 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package lib;
+
+import com.sun.star.beans.Property;
+import com.sun.star.beans.PropertyAttribute;
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.beans.XPropertySetInfo;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.uno.UnoRuntime;
+
+import java.lang.reflect.Method;
+
+import util.ValueChanger;
+import util.ValueComparer;
+import util.utils;
+
+import com.sun.star.uno.Any;
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.Type;
+
+/**
+ * MultiPropertyTest extends the functionality of MultiMethodTest to support
+ * services testing. Since, in most cases, service tests has one method testing
+ * most of its properties, the MultiPropertyTest provides unified version of
+ * the method: testProperty().
+ *
+ * <p>The testProperty() is called, when the MultiMethodTest's testing method
+ * is not found in the subclass. So, by defining such methods for properties
+ * the standard testing behavioutr can be changed.
+ *
+ * <p>The testing behaviour also can be changed by overriding compare(),
+ * getNewVAlue() or toString(Object) methods, or by extending PropertyTester
+ * class.
+ *
+ * @see MultiMethodTest
+ * @see #testProperty(String)
+ * @see #testProperty(String, Propertytester)
+ * @see #getNewValue
+ * @see #compare
+ * @see #toString(Object)
+ */
+public class MultiPropertyTest extends MultiMethodTest
+{
+
+ /**
+ * Contains a XPropertySet interface of the tested object. Is initialized
+ * in MultiMethodTest code.
+ */
+ public XPropertySet oObj;
+ protected boolean optionalService = false;
+
+ /**
+ * Overrides super.before() to check the service is supported by the object.
+ */
+ protected void before()
+ {
+ XServiceInfo xInfo = (XServiceInfo) UnoRuntime.queryInterface(
+ XServiceInfo.class, oObj);
+
+ optionalService = entry.isOptional;
+
+ String theService = getTestedClassName();
+ if (xInfo != null && !xInfo.supportsService(theService))
+ {
+ log.println("Service " + theService + " not available");
+ if (optionalService)
+ {
+ log.println("This is OK since it is optional");
+ }
+ else
+ {
+ Status.failed(theService + " is not supported");
+ }
+ }
+ }
+
+ /**
+ * Overrides MultiMethodTest.invokeTestMethod(). If the test for the
+ * <code>meth</code> is not available (<code>meth</code> == <tt>null</tt>)
+ * calls testProperty method for the method. Otherwise calls
+ * super.invokeTestMethod().
+ *
+ * @see #MultiMethodTest.invokeTestMethod()
+ */
+ protected void invokeTestMethod(Method meth, String methName)
+ {
+ if (meth != null)
+ {
+ super.invokeTestMethod(meth, methName);
+ }
+ else
+ {
+ testProperty(methName);
+ }
+ }
+
+ /**
+ * PropertyTester class defines how to test a property and defined
+ * to allow subclasses of MultiPropertyTest to change the testing
+ * behaviour more flexible, since the behaviour can be customized for
+ * each property separately, by providing subclass of PropertyTester
+ * and passing it to testProperty(String, PropertyTester method).
+ */
+ public class PropertyTester
+ {
+
+ /**
+ * The method defines the whole process of testing propName
+ * property.
+ *
+ * <p>First, it checks if the property exists(it maybe optional).
+ * Then, a value to set the property with is calculated with
+ * getNewValue method. Normally, the new value is calculated
+ * based on old value, but subclasses can override the behaviour
+ * (for example, if old value is null) and specify their own value.
+ * Then the property is set with that new value and the result(
+ * it maybe an exception too, for example a PropertyVetoException)
+ * is checked with checkResult method.
+ *
+ * @param propName - the property to test.
+ * @result - adds the result of testing propName property to
+ * MultiMethodTest.tRes.
+ */
+ protected void testProperty(String propName)
+ {
+ XPropertySetInfo info = oObj.getPropertySetInfo();
+
+ if (info != null)
+ {
+ final boolean bHasProperty = info.hasPropertyByName(propName);
+ if (!bHasProperty)
+ {
+ if (isOptional(propName) || optionalService)
+ {
+ // skipping optional property test
+ log.println("Property '" + propName + "' is optional and not supported");
+ tRes.tested(propName, true);
+ return;
+ }
+ else
+ {
+ // cannot test the property
+ log.println("Tested XPropertySet does not contain'" + propName + "' property");
+ tRes.tested(propName, false);
+ return;
+ }
+ }
+ }
+
+ try
+ {
+ Object oldValue = oObj.getPropertyValue(propName);
+
+ if( (oldValue==null) || utils.isVoid(oldValue) )
+ {
+ // #i111560# method getNewValue() does not work with an empty oldValue
+ Property prop = info.getPropertyByName(propName);
+ if( (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0 )
+ {
+ // todo: implement a new test independent from method getNewValue()
+ log.println("changing initially empty MAYBEVOID properties is not supported by the test framework so far - skip test of property: " + propName);
+ tRes.tested(propName, true);
+ return;
+ }
+ else
+ {
+ log.println( "property '"+propName+"' is not set but is not MAYBEVOID");
+ tRes.tested(propName, false);
+ return;
+ }
+ }
+
+ Object newValue;
+
+ // trying to create new value
+ try
+ {
+ newValue = getNewValue(propName, oldValue);
+ }
+ catch (java.lang.IllegalArgumentException e)
+ {
+ // skipping test since new value is not available
+ Status.failed("Cannot create new value for '" + propName + " : " + e.getMessage());
+ return;
+ }
+
+ // for an exception thrown during setting new value
+ // to pass it to checkResult method
+ Exception exception = null;
+
+ try
+ {
+ log.println("try to set:");
+ log.println("old = " + toString(oldValue));
+ log.println("new = " + toString(newValue));
+ oObj.setPropertyValue(propName, newValue);
+ }
+ catch (IllegalArgumentException e)
+ {
+ exception = e;
+ }
+ catch (PropertyVetoException e)
+ {
+ exception = e;
+ }
+ catch (WrappedTargetException e)
+ {
+ exception = e;
+ }
+ catch (UnknownPropertyException e)
+ {
+ exception = e;
+ }
+ catch (RuntimeException e)
+ {
+ exception = e;
+ }
+
+ // getting result value
+ Object resValue = oObj.getPropertyValue(propName);
+
+ // checking results
+ checkResult(propName, oldValue, newValue, resValue, exception);
+ }
+ catch (Exception e)
+ {
+ log.println("Exception occured while testing property '" + propName + "'");
+ e.printStackTrace(log);
+ tRes.tested(propName, false);
+ }
+ }
+
+ /**
+ * The method checks result of setting a new value to the
+ * property based o the following arguments:
+ * @propName - the property to test
+ * @oldValue - the old value of the property, before changing it.
+ * @newValue - the new value the property has been set with
+ * @resValue - the value of the property after having changed it
+ * @exception - if not null - the exception thrown by
+ * XPropertySet.setPropertyValue, else indicates
+ * normal method completion.
+ *
+ * <p>If the property is READ_ONLY, than either PropertyVetoException
+ * should be thrown or the value of property should not have changed
+ * (resValue is compared with oldValue with compare method).
+ *
+ * <p>If the property is not READ_ONLY, checks that the new value has
+ * been successfully set(resValue is compared with newValue with
+ * compare method).
+ *
+ * <p>If the exception is not null then(except the case of read-only
+ * property and PropertyVetoException above) it is rethrown to allow
+ * further catching it if needed.
+ *
+ * <p>Subclasses can override to change this behaviour.
+ */
+ protected void checkResult(String propName, Object oldValue,
+ Object newValue, Object resValue, Exception exception)
+ throws Exception
+ {
+ XPropertySetInfo info = oObj.getPropertySetInfo();
+ if (info == null)
+ {
+ log.println("Can't get XPropertySetInfo for property " + propName);
+ tRes.tested(propName, false);
+ return;
+ }
+ Property prop = info.getPropertyByName(propName);
+
+ short attr = prop.Attributes;
+ boolean readOnly = (prop.Attributes & PropertyAttribute.READONLY) != 0;
+ boolean maybeVoid = (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0;
+ //check get-set methods
+ if (maybeVoid)
+ {
+ log.println("Property " + propName + " is void");
+ }
+ if (readOnly)
+ {
+ log.println("Property " + propName + " is readOnly");
+ }
+ if (util.utils.isVoid(oldValue) && !maybeVoid)
+ {
+ log.println(propName + " is void, but it's not MAYBEVOID");
+ tRes.tested(propName, false);
+ }
+ else if (oldValue == null)
+ {
+ log.println(propName + " has null value, and therefore can't be changed");
+ tRes.tested(propName, true);
+ }
+ else if (readOnly)
+ {
+ // check if exception was thrown
+ if (exception != null)
+ {
+ if (exception instanceof PropertyVetoException)
+ {
+ // the change of read only prohibited - OK
+ log.println("Property is ReadOnly and wasn't changed");
+ log.println("Property '" + propName + "' OK");
+ tRes.tested(propName, true);
+ }
+ else if (exception instanceof IllegalArgumentException)
+ {
+ // the change of read only prohibited - OK
+ log.println("Property is ReadOnly and wasn't changed");
+ log.println("Property '" + propName + "' OK");
+ tRes.tested(propName, true);
+ }
+ else if (exception instanceof UnknownPropertyException)
+ {
+ // the change of read only prohibited - OK
+ log.println("Property is ReadOnly and wasn't changed");
+ log.println("Property '" + propName + "' OK");
+ tRes.tested(propName, true);
+ }
+ else if (exception instanceof RuntimeException)
+ {
+ // the change of read only prohibited - OK
+ log.println("Property is ReadOnly and wasn't changed");
+ log.println("Property '" + propName + "' OK");
+ tRes.tested(propName, true);
+ }
+ else
+ {
+ throw exception;
+ }
+ }
+ else
+ {
+ // if no exception - check that value
+ // has not changed
+ if (!compare(resValue, oldValue))
+ {
+ log.println("Read only property '" + propName + "' has changed");
+ try
+ {
+ if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
+ {
+ oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
+ }
+// log.println("old = " + toString(oldValue));
+// log.println("new = " + toString(newValue));
+ log.println("result = " + toString(resValue));
+ }
+ catch (com.sun.star.lang.IllegalArgumentException iae)
+ {
+ log.println("NOTIFY: this property needs further investigations.");
+ log.println("\t The type seems to be an Any with value of NULL.");
+ log.println("\t Maybe the property should get it's own test method.");
+ }
+
+ tRes.tested(propName, false);
+ }
+ else
+ {
+ log.println("Read only property '" + propName + "' hasn't changed");
+ log.println("Property '" + propName + "' OK");
+ tRes.tested(propName, true);
+ }
+ }
+ }
+ else
+ {
+ if (exception == null)
+ {
+ // if no exception thrown
+ // check that the new value is set
+ if ((!compare(resValue, newValue)) || (compare(resValue, oldValue)))
+ {
+ log.println("Value for '" + propName + "' hasn't changed as expected");
+ try
+ {
+ if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
+ {
+ oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
+ }
+// log.println("old = " + toString(oldValue));
+// log.println("new = " + toString(newValue));
+ log.println("result = " + toString(resValue));
+ }
+ catch (com.sun.star.lang.IllegalArgumentException iae)
+ {
+ log.println("NOTIFY: this property needs further investigations.");
+ log.println("\t The type seems to be an Any with value of NULL.");
+ log.println("\t Maybe the property should get it's own test method.");
+ }
+ if (resValue != null)
+ {
+ if ((!compare(resValue, oldValue)) || (!resValue.equals(oldValue)))
+ {
+ log.println("But it has changed.");
+ tRes.tested(propName, true);
+ }
+ else
+ {
+ tRes.tested(propName, false);
+ }
+ }
+ else
+ {
+ tRes.tested(propName, false);
+ }
+ //tRes.tested(propName, false);
+ }
+ else
+ {
+ log.println("Property '" + propName + "' OK");
+ try
+ {
+ if (!util.utils.isVoid(oldValue) && oldValue instanceof Any)
+ {
+ oldValue = AnyConverter.toObject(new Type(((Any) oldValue).getClass()), oldValue);
+ }
+// log.println("old = " + toString(oldValue));
+// log.println("new = " + toString(newValue));
+ log.println("result = " + toString(resValue));
+ }
+ catch (com.sun.star.lang.IllegalArgumentException iae)
+ {
+ }
+ tRes.tested(propName, true);
+ }
+ }
+ else
+ {
+ throw exception;
+ }
+ }
+ }
+
+ /**
+ * The method produces new value of the property from the oldValue.
+ * It returns the result of ValueChanger.changePValue method.
+ * Subclasses can override the method to return their own value,
+ * when the changePValue beahviour is not enough, for example,
+ * when oldValue is null.
+ */
+ protected Object getNewValue(String propName, Object oldValue)
+ throws java.lang.IllegalArgumentException
+ {
+ return ValueChanger.changePValue(oldValue);
+ }
+
+ /**
+ * The method compares obj1 and obj2. It calls
+ * MultiPropertyTest.compare, but subclasses can override to change
+ * the behaviour, since normally compare calls Object.equals method
+ * which is not apropriate in some cases(e.g., structs with equals
+ * not overridden).
+ */
+ protected boolean compare(Object obj1, Object obj2)
+ {
+ return callCompare(obj1, obj2);
+ }
+
+ /**
+ * The method returns a String representation of the obj. It calls
+ * MultipropertyTest.toString(Object), but subclasses can override
+ * to change the behaviour.
+ */
+ protected String toString(Object obj)
+ {
+ return callToString(obj);
+ }
+ }
+
+ /**
+ * Extension for <code>PropertyTester</code> which switches two
+ * different values. <code>getNewValue()</code> method of this
+ * class returns one of these two values depending on the
+ * old value, so new value is not equal to old value.
+ */
+ public class PropertyValueSwitcher extends PropertyTester
+ {
+
+ Object val1 = null;
+ Object val2 = null;
+
+ /**
+ * Constructs a property tester with two different values
+ * specified as parameters.
+ *
+ * @param val1 Not <code>null</code> value for the property
+ * tested.
+ * @param val1 Not <code>null</code> value for the property
+ * tested which differs from the first value.
+ */
+ public PropertyValueSwitcher(Object val1, Object val2)
+ {
+ this.val1 = val1;
+ this.val2 = val2;
+ }
+
+ /**
+ * Overriden method of <code>PropertyTester</code> which
+ * retruns new value from two values specified.
+ *
+ * @return The second value if old value is equal to the first
+ * one, the first value otherwise.
+ */
+ protected Object getNewValue(String propName, Object old)
+ {
+ if (ValueComparer.equalValue(val1, old))
+ {
+ return val2;
+ }
+ else
+ {
+ return val1;
+ }
+ }
+ }
+
+ /**
+ * The method performs testing of propName property using propTester.
+ */
+ protected void testProperty(String propName, PropertyTester propTester)
+ {
+ propTester.testProperty(propName);
+ }
+
+ /**
+ * The method performs testing of propName property. It uses PropertyTester
+ * instance for testing.
+ */
+ protected void testProperty(String propName)
+ {
+ testProperty(propName, new PropertyTester());
+ }
+
+ /**
+ * Tests the property using <code>PropertyValueSwitcher</code>
+ * tester and two values for this property.
+ *
+ * @see #PropertyValueSwitcher
+ */
+ protected void testProperty(String propName, Object val1, Object val2)
+ {
+ testProperty(propName, new PropertyValueSwitcher(val1, val2));
+ }
+
+ /**
+ * The method just calls compare. This is a workaround to CodeWarrior's
+ * compiler bug.
+ */
+ private boolean callCompare(Object obj1, Object obj2)
+ {
+ return compare(obj1, obj2);
+ }
+
+ /**
+ * Compares two object. In the implementation calls obj1.equals(obj2).
+ */
+ protected boolean compare(Object obj1, Object obj2)
+ {
+ return ValueComparer.equalValue(obj1, obj2);
+ }
+
+ /**
+ * The method just calls toString. This is a workaround to
+ * CodeWarrior's compiler bug.
+ */
+ private String callToString(Object obj)
+ {
+ return toString(obj);
+ }
+
+ /**
+ * Gets string representation of the obj. In the implementation
+ * returns obj.toString().
+ */
+ protected String toString(Object obj)
+ {
+ return obj == null ? "null" : obj.toString();
+ }
+}