summaryrefslogtreecommitdiffstats
path: root/qadevOOo/runner/complexlib
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /qadevOOo/runner/complexlib
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'qadevOOo/runner/complexlib')
-rw-r--r--qadevOOo/runner/complexlib/Assurance.java146
-rw-r--r--qadevOOo/runner/complexlib/ComplexTestCase.java296
-rw-r--r--qadevOOo/runner/complexlib/MethodThread.java118
-rw-r--r--qadevOOo/runner/complexlib/ShowTargets.java102
4 files changed, 662 insertions, 0 deletions
diff --git a/qadevOOo/runner/complexlib/Assurance.java b/qadevOOo/runner/complexlib/Assurance.java
new file mode 100644
index 0000000000..4fbf3755d6
--- /dev/null
+++ b/qadevOOo/runner/complexlib/Assurance.java
@@ -0,0 +1,146 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package complexlib;
+
+/**
+ * I have removed the assure(...) functions from ComplexTestCase due to the fact now I can
+ * use the functions every where and don't need to be a ComplexTestCase any longer.
+ */
+public class Assurance
+{
+ /** Used to indicate that we should continue with test method, even if check fails */
+ public enum ContinueWithTest {
+ YES, NO
+ }
+
+ /** State of the current test method **/
+ protected boolean bSuccessful = true;
+
+ /** The message if the test did fail **/
+ protected String message = null;
+
+
+ /**
+ * Assure that s is true.
+ * This function generates "Assure failed." as standard message.
+ * @param s The condition that should be true.
+ */
+ protected void assure(boolean s) {
+ assure("Assure failed.", s, ContinueWithTest.NO);
+ }
+
+ /**
+ * Assure that s is true.
+ * The given message will be only evaluated, if s is false.
+ * @param msg The message that is evaluated.
+ * @param s The condition that should be true.
+ */
+ protected void assure(String msg, boolean s) {
+ assure(msg, s, ContinueWithTest.NO);
+ }
+
+ /**
+ * Assure that two int values are equal
+ * @param message the message to print when the equality test fails
+ * @param expected specifies the expected int value
+ * @param actual specifies the actual int value
+ */
+ protected void assureEquals( String message, int expected, int actual ) {
+ assureEquals( message, Integer.valueOf( expected ), Integer.valueOf( actual ), ContinueWithTest.NO );
+ }
+
+ /**
+ * Assure that two string values are equal
+ * @param message the message to print when the equality test fails
+ * @param expected specifies the expected string value
+ * @param actual specifies the actual string value
+ */
+ protected void assureEquals( String message, String expected, String actual ) {
+ assureEquals( message, expected, actual, ContinueWithTest.NO );
+ }
+
+ /**
+ * assures the two given sequences are of equal length, and have equal content
+ */
+ public <T> void assureEquals( String i_message, T[] i_expected, T[] i_actual, ContinueWithTest i_continue )
+ {
+ if ( i_expected.length != i_actual.length )
+ failed( i_message + ": expected element count: " + i_expected.length + ", actual element count: " + i_actual.length );
+ for ( int i=0; i<i_expected.length; ++i )
+ {
+ assureEquals( i_message + ": mismatch at element pos " + i, i_expected[i], i_actual[i], i_continue );
+ }
+ }
+
+ /**
+ * Mark the currently executed method as failed.
+ * with the given message.
+ * @param msg The message of the failure.
+ */
+ protected void failed(String msg) {
+ assure(msg, false, ContinueWithTest.NO);
+ }
+
+ /**
+ * Assure that s is true.
+ * The given message will be only evaluated, if s is false.
+ * Normally, assure() leaves the current test method, and the next one
+ * is executed. With the parameter 'cont' set to true, the current test
+ * method will continue.<br>
+ * The current method will of course marked as failed.
+ * @param msg The message that is evaluated.
+ * @param s The condition that should be true.
+ * @param cont if YES, continue with test method, even if s is false.
+ */
+ protected void assure(String msg, boolean s, ContinueWithTest cont) {
+ bSuccessful &= s;
+ if (!s) {
+ message += msg + "\r\n";
+ if (cont == ContinueWithTest.NO) {
+ throw new AssureException(msg);
+ }
+ }
+ }
+
+ private void assureEquals( String message, Object expected, Object actual, ContinueWithTest cont ) {
+ assure( message + " (expected: " + expected.toString() + ", actual: " + actual.toString() + ")",
+ expected.equals( actual ), cont );
+ }
+
+ /**
+ * Mark the currently executed method as failed.
+ * with the given message.
+ * The given message will be only evaluated, if s is false.
+ * With the parameter 'cont' set to true, the current test
+ * method will continue.<br>
+ * The current method will of course marked as failed.
+ * @param msg The message that is evaluated.
+ * @param cont if YES, continue with test method, even if s is false.
+ */
+ protected void failed(String msg, ContinueWithTest cont) {
+ assure(msg, false, cont);
+ }
+
+ public static class AssureException extends RuntimeException {
+
+ private AssureException(String msg) {
+ super(msg);
+ }
+ }
+}
diff --git a/qadevOOo/runner/complexlib/ComplexTestCase.java b/qadevOOo/runner/complexlib/ComplexTestCase.java
new file mode 100644
index 0000000000..ab95d1eed0
--- /dev/null
+++ b/qadevOOo/runner/complexlib/ComplexTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complexlib;
+
+import java.lang.reflect.Method;
+import share.DescEntry;
+import lib.TestParameters;
+import lib.StatusException;
+import share.LogWriter;
+import share.ComplexTest;
+import java.io.PrintWriter;
+
+/**
+ * Base class for all complex tests.
+ */
+public abstract class ComplexTestCase extends Assurance implements ComplexTest
+{
+
+ /** The test parameters **/
+ protected TestParameters param = null;
+ /** Log writer **/
+ protected LogWriter log = null;
+ /**
+ * The method name which will be written into f.e. the data base
+ **/
+ private String mTestMethodName = null;
+
+ private boolean m_bBeforeCalled;
+
+ /**
+ * is called before the real test starts
+ */
+ private void before()
+ {
+ try
+ {
+ Method before = this.getClass().getMethod("before", new Class[] {} );
+ before.invoke(this, new Object[] {} );
+
+ m_bBeforeCalled = true;
+ }
+ catch (java.lang.NoSuchMethodException e)
+ {
+ m_bBeforeCalled = true;
+ }
+ catch (java.lang.IllegalAccessException e)
+ {
+ log.println("Cannot access the 'before()' method, although it" + " is there. Is this ok?");
+ }
+ catch (java.lang.reflect.InvocationTargetException e)
+ {
+ Throwable t = e.getTargetException();
+ if (!(t instanceof RuntimeException) || bSuccessful)
+ {
+ log.println(t.toString());
+ if (message == null)
+ {
+ message = "Exception in before() method.\n\r" + t.getMessage();
+ }
+ bSuccessful = false;
+ t.printStackTrace((PrintWriter) log);
+ }
+ }
+
+ }
+
+ /** Description entry **/
+
+ private void test_method(DescEntry _entry)
+ {
+
+ /* Maximal time one method is allowed to execute
+ * Can be set with parameter 'ThreadTimeOut'
+ **/
+ int nThreadTimeOut = param.getInt("ThreadTimeOut");
+ if (nThreadTimeOut == 0)
+ {
+ nThreadTimeOut = 300000;
+ }
+
+ for (int i = 0; i < _entry.SubEntries.length; i++)
+ {
+
+ DescEntry subEntry = _entry.SubEntries[i];
+ if (m_bBeforeCalled)
+ {
+ bSuccessful = true;
+ message = "";
+ }
+ else
+ {
+ // set all test methods on failed, if 'before()' did not work.
+ subEntry.State = message;
+ subEntry.hasErrorMsg = true;
+ subEntry.ErrorMsg = message;
+ continue;
+ }
+ Method testMethod = null;
+ try
+ {
+ String entryName = subEntry.entryName;
+ Object[] parameter = null;
+
+ int posLeftParenthesis = entryName.indexOf('(');
+ if (posLeftParenthesis != -1)
+ {
+ String sParameter = entryName.substring(posLeftParenthesis + 1, entryName.indexOf(')'));
+ mTestMethodName = entryName;
+ parameter = new String[] { sParameter };
+ entryName = entryName.substring(0, posLeftParenthesis);
+ testMethod = this.getClass().getMethod(entryName, new Class[] { String.class });
+ }
+ else
+ {
+ testMethod = this.getClass().getMethod(entryName, new Class[] {} );
+ mTestMethodName = entryName;
+ }
+
+ MethodThread th = new MethodThread(testMethod, this, parameter, (java.io.PrintWriter) log);
+ log.println("Starting " + mTestMethodName);
+ th.start();
+
+ try
+ {
+ // some tests are very dynamic in their execution time so that
+ // a threadTimeOut fails. In this cases the logging mechanism
+ // is a useful way to detect that an office respective a test
+ // is running and not death.
+ // But way ThreadTimeOut?
+ // There exists a complex test which uses no office. Therefore
+ // a logging mechanism to detect a stalled test.
+ int lastPing = -1;
+ int newPing = 0;
+
+ int sleepingStep = 1000;
+ int factor = 0;
+
+ while (th.isAlive() && (lastPing != newPing || factor * sleepingStep < nThreadTimeOut))
+ {
+ Thread.sleep(sleepingStep);
+ factor++;
+ // if a test starts the office itself it the watcher is a
+ // new one.
+ share.Watcher ow = (share.Watcher) param.get("Watcher");
+ if (ow != null)
+ {
+ lastPing = newPing;
+ newPing = ow.getPing();
+ factor = 0;
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ }
+ if (th.isAlive())
+ {
+ log.println("Destroy " + mTestMethodName);
+ th.stopRunning();
+ subEntry.State = "Test did sleep for " + (nThreadTimeOut / 1000) + " seconds and has been killed!";
+ subEntry.hasErrorMsg = true;
+ subEntry.ErrorMsg = subEntry.State;
+ continue;
+ }
+ else
+ {
+ log.println("Finished " + mTestMethodName);
+ if (th.hasErrorMessage())
+ {
+ subEntry.State = th.getErrorMessage();
+ subEntry.hasErrorMsg = true;
+ subEntry.ErrorMsg = subEntry.State;
+ continue;
+ }
+ }
+ }
+ catch (java.lang.Exception e)
+ {
+ log.println(e.getClass().getName());
+ String msg = e.getMessage();
+ log.println("Message: " + msg);
+ e.printStackTrace((PrintWriter) log);
+ subEntry.State = "SKIPPED.FAILED";
+ subEntry.hasErrorMsg = true;
+ subEntry.ErrorMsg = (msg == null ? "" : msg);
+ continue;
+ }
+ subEntry.State = (bSuccessful ? "COMPLETED.OK" : message);
+ subEntry.hasErrorMsg = !bSuccessful;
+ subEntry.ErrorMsg = message;
+ }
+ }
+
+ /**
+ * after() is called after the test is done
+ */
+ private void after()
+ {
+ if (m_bBeforeCalled)
+ {
+ // the after() method
+ try
+ {
+ Method after = this.getClass().getMethod("after", new Class[] {});
+ after.invoke(this, new Object[] {} );
+ }
+ catch (java.lang.NoSuchMethodException e)
+ {
+ // simply ignore
+ }
+ catch (java.lang.IllegalAccessException e)
+ {
+ // simply ignore
+ }
+ catch (java.lang.reflect.InvocationTargetException e)
+ {
+ Throwable t = e.getTargetException();
+ if (!(t instanceof StatusException))
+ {
+ log.println(t.toString());
+ if (message == null)
+ {
+ message = "Exception in after() method.\n\r" + t.getMessage();
+ }
+ else
+ {
+ message += "Exception in \'after()\' method.\n\r" + t.getMessage();
+ }
+ log.println("Message: " + message);
+ t.printStackTrace((PrintWriter) log);
+ }
+ }
+ }
+
+ }
+
+
+
+ /**
+ * Call test. It is expected, that an environment is
+ * given to this test.
+ *
+ * @param entry The name of the test method that should be called.
+ * @param environment The environment for the test.
+ */
+ public void executeMethods(DescEntry entry, TestParameters environment)
+ {
+ m_bBeforeCalled = false;
+
+ // get the environment
+ param = environment;
+ log = entry.Logger;
+
+
+ // start with the before() method
+ before();
+
+ //executeMethodTests
+ test_method(entry);
+
+ // cleanup
+ after();
+ }
+
+
+ /**
+ * Implement this method in the Complex test.
+ * @return All test method names.
+ */
+ public abstract String[] getTestMethodNames();
+
+ /**
+ * Return a name for the test or tested object.
+ * Override to give an own name.
+ * @return As default, the name of this class.
+ */
+ public String getTestObjectName()
+ {
+ return this.getClass().getName();
+ }
+}
diff --git a/qadevOOo/runner/complexlib/MethodThread.java b/qadevOOo/runner/complexlib/MethodThread.java
new file mode 100644
index 0000000000..28ea770eb9
--- /dev/null
+++ b/qadevOOo/runner/complexlib/MethodThread.java
@@ -0,0 +1,118 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package complexlib;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Method;
+
+/**
+ * Invoke a method of a class in an own thread. Provide a method to end
+ * the thread.
+ */
+public class MethodThread extends Thread
+{
+
+ /** The method that should be executed **/
+ private final Method mTestMethod;
+ /** The object that implements the method **/
+ private final Object mInvokeClass;
+ /** A PrintWriter for debug Output **/
+ private final PrintWriter mLog;
+ /** An Error String **/
+ private String mErrMessage = null;
+ /** Did an Exception happen? **/
+ private boolean mExceptionHappened = false;
+ private Object[] mParameter = null;
+
+ public MethodThread(Method testMethod, Object invokeClass, Object[] parameter, PrintWriter log)
+ {
+ mTestMethod = testMethod;
+ mInvokeClass = invokeClass;
+ mParameter = parameter;
+ mLog = log;
+ }
+
+ /**
+ * Invoke the method.
+ */
+ @Override
+ public void run()
+ {
+ try
+ {
+ mTestMethod.invoke(mInvokeClass, mParameter);
+ }
+ catch (IllegalAccessException e)
+ {
+ e.printStackTrace(mLog);
+ mErrMessage = e.getMessage();
+ mExceptionHappened = true;
+ }
+ catch (java.lang.reflect.InvocationTargetException e)
+ {
+ Throwable t = e.getTargetException();
+ if (!(t instanceof ComplexTestCase.AssureException))
+ {
+ t.printStackTrace(mLog);
+ mErrMessage = t.getMessage();
+ if (mErrMessage == null)
+ {
+ mErrMessage = t.toString();
+ }
+ mExceptionHappened = true;
+ }
+
+ }
+ }
+
+ /**
+ * Get the error message
+ * @return The error message.
+ */
+ public String getErrorMessage()
+ {
+ return mErrMessage;
+ }
+
+ /**
+ * Is there an error message?
+ * @return True, if an error did happen.
+ */
+ public boolean hasErrorMessage()
+ {
+ return mExceptionHappened;
+ }
+
+ /**
+ * Stop the running method.
+ */
+ public void stopRunning()
+ {
+ try
+ {
+ interrupt();
+ }
+ catch (SecurityException e)
+ {
+ e.printStackTrace(mLog);
+ mErrMessage = e.getMessage();
+ mExceptionHappened = true;
+ }
+ }
+}
diff --git a/qadevOOo/runner/complexlib/ShowTargets.java b/qadevOOo/runner/complexlib/ShowTargets.java
new file mode 100644
index 0000000000..f655e1330c
--- /dev/null
+++ b/qadevOOo/runner/complexlib/ShowTargets.java
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package complexlib;
+
+import java.util.ArrayList;
+
+public class ShowTargets
+{
+ public static void main( String[] args )
+ {
+ ArrayList<String> targets = new ArrayList<String>();
+ ArrayList<String> descs = new ArrayList<String>();
+
+ targets.add( "run" );
+ descs.add( "runs all complex tests in this module" );
+
+ int maxTargetLength = 3;
+
+ for ( int i = 0; i < args.length; ++i )
+ {
+ String completePotentialClassName = args[i].replace( '/', '.' );
+
+ // filter
+ if ( completePotentialClassName.endsWith( ".TestCase" ) )
+ continue;
+ if ( completePotentialClassName.endsWith( ".TestSkeleton" ) )
+ continue;
+
+ // get the class
+ Class<?> potentialTestClass = null;
+ try { potentialTestClass = Class.forName( completePotentialClassName ); }
+ catch( java.lang.ClassNotFoundException e )
+ {
+ continue;
+ }
+
+ // see if it is derived from complexlib.ComplexTestCase
+ Class<?> superClass = potentialTestClass.getSuperclass();
+ while ( superClass != null )
+ {
+ if ( superClass.getName().equals( "complexlib.ComplexTestCase" ) )
+ {
+ String bareClassName = completePotentialClassName.substring( completePotentialClassName.lastIndexOf( '.' ) + 1 );
+ String target = "run_" + bareClassName;
+ targets.add( target );
+ descs.add( getShortTestDescription( potentialTestClass ) );
+
+ if ( maxTargetLength < target.length() )
+ maxTargetLength = target.length();
+ break;
+ }
+ superClass = superClass.getSuperclass();
+ }
+ }
+
+ System.out.println( "possible targets:" );
+ for ( int i=0; i<targets.size(); ++i )
+ {
+ // target
+ String target = targets.get(i);
+ // 'tab'
+ System.out.print( " " + target );
+ for ( int s = maxTargetLength - target.length(); s>0; --s )
+ System.out.print( " " );
+ // description
+ System.out.println( " (" + descs.get(i) + ")" );
+ }
+ }
+
+ private static String getShortTestDescription( Class<?> _testClass )
+ {
+ java.lang.reflect.Method getShortDescriptionMethod = null;
+ try { getShortDescriptionMethod = _testClass.getMethod( "getShortTestDescription", new Class[]{} ); }
+ catch( Exception e ) { }
+
+ if ( getShortDescriptionMethod != null )
+ {
+ try
+ {
+ return (String)getShortDescriptionMethod.invoke( null, new Object[]{} );
+ }
+ catch( Exception e ) { }
+ }
+ return "no description provided by the test";
+ }
+}