/*******************************************************************************
* Copyright (c) 2013 Rene Schneider, GEBIT Solutions GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package de.gebit.integrity.runner.callbacks;
import java.io.Serializable;
import de.gebit.integrity.dsl.Call;
import de.gebit.integrity.dsl.ConstantEntity;
import de.gebit.integrity.dsl.ForkDefinition;
import de.gebit.integrity.dsl.Suite;
import de.gebit.integrity.dsl.SuiteDefinition;
import de.gebit.integrity.dsl.SuiteReturn;
import de.gebit.integrity.dsl.TableTest;
import de.gebit.integrity.dsl.TableTestRow;
import de.gebit.integrity.dsl.Test;
import de.gebit.integrity.dsl.VariableAssignment;
import de.gebit.integrity.dsl.VariableEntity;
import de.gebit.integrity.dsl.VariantDefinition;
import de.gebit.integrity.dsl.VisibleComment;
import de.gebit.integrity.dsl.VisibleDivider;
import de.gebit.integrity.remoting.server.IntegrityRemotingServer;
import de.gebit.integrity.remoting.transport.enums.TestRunnerCallbackMethods;
import de.gebit.integrity.runner.TestModel;
import de.gebit.integrity.runner.results.SuiteResult;
import de.gebit.integrity.runner.results.SuiteSummaryResult;
import de.gebit.integrity.runner.results.call.CallResult;
import de.gebit.integrity.runner.results.test.TestResult;
import de.gebit.integrity.runner.results.test.TestSubResult;
/**
* During test execution, the test runner invokes a callback in order to report progress as well as test results. A
* callback can then use this information for whatever purpose; usually writing test output files.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public abstract class TestRunnerCallback {
/**
* Called when a call to all callbacks is imminent.
*/
public void onCallbackProcessingStart() {
// do nothing; can be overridden if callback wants to be notified when the test runner starts calling the
// callbacks
}
/**
* Called after a call has been performed on all callbacks.
*/
public void onCallbackProcessingEnd() {
// do nothing; can be overridden if callback wants to be notified when the test runner has finished calling
// the callbacks
}
/**
* Called when the execution starts, that is, before the first (root) suite is entered. This is always the first
* call of an execution phase.
*
* @param aModel
* the test model that will be executed
*/
public abstract void onExecutionStart(TestModel aModel, VariantDefinition aVariant);
/**
* Called when a suite call is being followed.
*
* @param aSuite
* the suite call that will be entered
*/
public abstract void onSuiteStart(Suite aSuite);
/**
* Called when a setup suite is being called.
*
* @param aSetupSuite
* the setup suite being entered
*/
public abstract void onSetupStart(SuiteDefinition aSetupSuite);
/**
* Called when a setup suite has been executed.
*
* @param aSetupSuite
* the setup suite that was executed
* @param aResult
* the result of the execution
*/
public abstract void onSetupFinish(SuiteDefinition aSetupSuite, SuiteResult aResult);
/**
* Called right before a test is being executed.
*
* @param aTest
* the test
*/
public abstract void onTestStart(Test aTest);
/**
* Called after a test was executed.
*
* @param aTest
* the test that was executed
* @param aResult
* the result of the execution
*/
public abstract void onTestFinish(Test aTest, TestResult aResult);
/**
* Called when a table test is about to be executed.
*
* @param aTableTest
* the table test
*/
public abstract void onTableTestStart(TableTest aTableTest);
/**
* Called when a single row of a table test is about to be executed.
*
* @param aTableTest
* the table test that contains the row
* @param aRow
* the row
*/
public abstract void onTableTestRowStart(TableTest aTableTest, TableTestRow aRow);
/**
* Called after a table test row has been executed.
*
* @param aTableTest
* the table test that contains the row
* @param aRow
* the row that was executed
* @param aSubResult
* the result of the execution
*/
public abstract void onTableTestRowFinish(TableTest aTableTest, TableTestRow aRow, TestSubResult aSubResult);
/**
* Called after a tabletest was fully executed (all rows have been executed).
*
* @param aTableTest
* the table test
* @param aResult
* the result of the test execution
*/
public abstract void onTableTestFinish(TableTest aTableTest, TestResult aResult);
/**
* Called before a call is being executed.
*
* @param aCall
* the call
*/
public abstract void onCallStart(Call aCall);
/**
* Called right after a call was executed.
*
* @param aCall
* the call
* @param aResult
* the result of the execution
*/
public abstract void onCallFinish(Call aCall, CallResult aResult);
/**
* Called before a teardown suite is being executed.
*
* @param aTearDownSuite
* the suite to be executed
*/
public abstract void onTearDownStart(SuiteDefinition aTearDownSuite);
/**
* Called after a teardown suite was executed.
*
* @param aTearDownSuite
* the suite that was executed
* @param aResult
* the result of the execution
*/
public abstract void onTearDownFinish(SuiteDefinition aTearDownSuite, SuiteResult aResult);
/**
* Called after a suite has finished execution. This might return a {@link SuiteResult} instance if the suite was
* executed locally, or a {@link SuiteSummaryResult} with just the summary count information if the suite ran on a
* fork, in which case the detailed information is not available.
*
* @param aSuite
* the suite that was executed
* @param aResult
* the result of the execution
*/
public abstract void onSuiteFinish(Suite aSuite, SuiteSummaryResult aResult);
/**
* Called after all execution has been finished. This is always the last call of an execution phase.
*
* @param aModel
* @param aResult
*/
public abstract void onExecutionFinish(TestModel aModel, SuiteSummaryResult aResult);
/**
* Called when a variable is being defined.
*
* @param aDefinition
* the variable
* @param aSuite
* the suite in which the variable is scoped (may be null if the variable is global)
* @param anInitialValue
* the initial value (may be null if no initial value is given)
*/
public abstract void onVariableDefinition(VariableEntity aDefinition, SuiteDefinition aSuite,
Object anInitialValue);
/**
* Called when a constant is being defined.
*
* @param aDefinition
* the constant
* @param aSuite
* the suite in which the constant is scoped (may be null if the constant is global)
* @param aValue
* the value (may be null if no value was given)
* @param aParameterizedFlag
* true if the constant was parameterized (value defined not in script, but from outside the test runner
* via parameter)
*/
public abstract void onConstantDefinition(ConstantEntity aDefinition, SuiteDefinition aSuite, Object aValue,
boolean aParameterizedFlag);
/**
* Called when a variable is being assigned.
*
* @param anAssignment
* the assignment
* @param aDefinition
* the variable that the value is to be assigned
* @param aSuite
* the suite in which the variable is scoped (may be null if the variable is global)
* @param aValue
* the value
*/
public abstract void onVariableAssignment(VariableAssignment anAssignment, VariableEntity aDefinition,
SuiteDefinition aSuite, Object aValue);
/**
* Called when a return variable value from a suite is assigned to the respective local variable in the calling
* suite.
*
* @param aReturn
* the return variable object
* @param aSource
* the source variable entity
* @param aTarget
* the target variable entity
* @param aSuite
* the suite invocation for which the assignment is done
* @param aValue
* the value to be assigned
*/
public abstract void onReturnVariableAssignment(SuiteReturn aReturn, VariableEntity aSource, VariableEntity aTarget,
Suite aSuite, Object aValue);
/**
* Called when a visible comment is encountered during execution.
*
* @param aCommentText
* the text inside the comment
* @param aCommentElement
* the raw comment element
*/
public abstract void onVisibleComment(String aCommentText, boolean anIsTitle, VisibleComment aCommentElement);
/**
* Called when a visible divider is encountered during execution.
*
* @param aDividerText
* the divider text (basically a String of '-' chars with minimum length of 3 chars)
* @param aDividerElement
* the raw divider element
*/
public abstract void onVisibleDivider(String aDividerText, VisibleDivider aDividerElement);
/**
* Called when a fork has sent a message to the masters' callback. In order to merge results determined by forks
* seamlessly into the masters' results, callbacks do automatically have a simple messaging system at their
* disposal. When a fork callback uses {@link #sendToMaster(TestRunnerCallbackMethods, Serializable...)}, this
* method is called on the masters' respective callback in order to deliver the objects given.
*
* @param aMethod
* the method that was called on the forks' callback (doesn't have to be used, evaluating this parameter
* is the job of the masters' callback and can thus be omitted if it ain't necessary)
* @param someObjects
* the objects sent by the forks' callback
*/
public abstract void onMessageFromFork(TestRunnerCallbackMethods aMethod, Serializable... someObjects);
/**
* Called when test execution is aborted prematurely due to an
* {@link de.gebit.integrity.exceptions.AbortExecutionException} - either thrown locally or by a fork. The original
* exception can't be provided since it cannot be received from a fork by remoting. Instead, the data from the
* exception is provided in both cases.
*
* @param anAbortExecutionMessage
* the message from the exception
* @param anAbortExecutionStackTrace
* the stack trace of the exception
*/
public abstract void onAbortExecution(String anAbortExecutionMessage, String anAbortExecutionStackTrace);
/**
* The remoting server, required for callback-to-callback communication in master-fork situations.
*/
protected IntegrityRemotingServer server;
/**
* Whether the current phase is a dry run.
*/
protected boolean dryRun;
/**
* The fork that is currently being executed.
*/
protected ForkDefinition forkInExecution;
public void setRemotingServer(IntegrityRemotingServer aRemotingServer) {
server = aRemotingServer;
}
public void setDryRun(boolean aDryRun) {
dryRun = aDryRun;
}
public boolean isFork() {
return (server != null);
}
public boolean isDryRun() {
return dryRun;
}
public void setForkInExecution(ForkDefinition aFork) {
forkInExecution = aFork;
}
public ForkDefinition getForkInExecution() {
return forkInExecution;
}
/**
* When a callback that is running inside a fork instance uses this method, the given objects and the method
* parameter are being sent to the respective callback instance on the master. This mechanism is designed to allow
* for seamless integration of fork results into the masters' results.
*
* @param aMethod
* the method that was executed (doesn't have to be used, since the callback itself is responsible to
* parse this value)
* @param someObjects
* the objects to be sent
*/
protected void sendToMaster(TestRunnerCallbackMethods aMethod, Serializable... someObjects) {
if (server != null) {
server.sendTestRunnerCallbackData(getClass().getName(), aMethod, someObjects);
}
}
/**
* This method is used by the test runner to forward messages received from the forks to the callback.
*
* @param aCallbackClassName
* the callback class name
* @param aMethod
* the method called
* @param someData
* the objects given by the fork
*/
public void receiveFromFork(String aCallbackClassName, TestRunnerCallbackMethods aMethod, Serializable[] someData) {
if (getClass().getName().equals(aCallbackClassName)) {
onMessageFromFork(aMethod, someData);
}
}
}