blob: 0b7e98d4af9652077e47fd04b9013f8656e36480 [file] [log] [blame]
/**
*/
package org.eclipse.ease.lang.unittest.runtime.impl;
import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.core.runtime.IPath;
import org.eclipse.ease.IDebugEngine;
import org.eclipse.ease.IScriptEngine;
import org.eclipse.ease.Script;
import org.eclipse.ease.ScriptResult;
import org.eclipse.ease.lang.unittest.TestSuiteScriptEngine;
import org.eclipse.ease.lang.unittest.definition.Flag;
import org.eclipse.ease.lang.unittest.definition.ICode;
import org.eclipse.ease.lang.unittest.definition.ITestSuiteDefinition;
import org.eclipse.ease.lang.unittest.execution.ITestExecutionStrategy;
import org.eclipse.ease.lang.unittest.runtime.IRuntimeFactory;
import org.eclipse.ease.lang.unittest.runtime.IRuntimePackage;
import org.eclipse.ease.lang.unittest.runtime.ITestClass;
import org.eclipse.ease.lang.unittest.runtime.ITestEntity;
import org.eclipse.ease.lang.unittest.runtime.ITestFile;
import org.eclipse.ease.lang.unittest.runtime.ITestResult;
import org.eclipse.ease.lang.unittest.runtime.ITestSuite;
import org.eclipse.ease.lang.unittest.runtime.TestStatus;
import org.eclipse.ease.service.IScriptService;
import org.eclipse.ease.service.ScriptService;
import org.eclipse.ease.service.ScriptType;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
/**
* <!-- begin-user-doc --> An implementation of the model object '<em><b>Test File</b></em>'. <!-- end-user-doc -->
* <p>
* The following features are implemented:
* </p>
* <ul>
* <li>{@link org.eclipse.ease.lang.unittest.runtime.impl.TestFile#getInsertionOrder <em>Insertion Order</em>}</li>
* </ul>
*
* @generated
*/
public class TestFile extends TestContainer implements ITestFile {
/** Script engine used while executing the test file content. May be <code>null</code>. */
private IScriptEngine fScriptEngine = null;
/**
* The default value of the '{@link #getInsertionOrder() <em>Insertion Order</em>}' attribute. <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @see #getInsertionOrder()
* @generated
* @ordered
*/
protected static final int INSERTION_ORDER_EDEFAULT = 0;
/**
* The cached value of the '{@link #getInsertionOrder() <em>Insertion Order</em>}' attribute. <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @see #getInsertionOrder()
* @generated
* @ordered
*/
protected int insertionOrder = INSERTION_ORDER_EDEFAULT;
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
protected TestFile() {
super();
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
protected EClass eStaticClass() {
return IRuntimePackage.Literals.TEST_FILE;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
public int getInsertionOrder() {
return insertionOrder;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
public void setInsertionOrder(int newInsertionOrder) {
final int oldInsertionOrder = insertionOrder;
insertionOrder = newInsertionOrder;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, IRuntimePackage.TEST_FILE__INSERTION_ORDER, oldInsertionOrder, insertionOrder));
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case IRuntimePackage.TEST_FILE__INSERTION_ORDER:
return getInsertionOrder();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case IRuntimePackage.TEST_FILE__INSERTION_ORDER:
setInsertionOrder((Integer) newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case IRuntimePackage.TEST_FILE__INSERTION_ORDER:
setInsertionOrder(INSERTION_ORDER_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case IRuntimePackage.TEST_FILE__INSERTION_ORDER:
return insertionOrder != INSERTION_ORDER_EDEFAULT;
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
*/
@Override
public String toString() {
if (eIsProxy())
return super.toString();
final StringBuffer result = new StringBuffer(super.toString());
result.append(" (insertionOrder: ");
result.append(insertionOrder);
result.append(')');
return result.toString();
}
/**
* @generated NOT
*/
@Override
public void run(ITestExecutionStrategy strategy) {
// first check for disabled tests
if (TestStatus.DISABLED.equals(getStatus()))
return;
fScriptEngine = strategy.createScriptEngine(getTestSuite(), getResource());
if (fScriptEngine != null) {
setEntityStatus(TestStatus.RUNNING);
// execute resource
try {
fScriptEngine.setVariable(TestSuiteScriptEngine.TEST_FILE_VARIABLE, this);
fScriptEngine.setVariable(TestSuiteScriptEngine.TEST_SUITE_VARIABLE, getTestSuite());
fScriptEngine.setTerminateOnIdle(false);
fScriptEngine.schedule();
// testfile setup
runSetupTeardownCode(ITestSuiteDefinition.CODE_LOCATION_TESTFILE_SETUP);
// classic test execution
if (!hasError()) {
ScriptResult executionResult = fScriptEngine.executeSync(getResource());
if (executionResult.hasException()) {
// we should mark the last test as invalid
if (!getChildren().isEmpty()) {
final ITestEntity test = getChildren().get(getChildren().size() - 1);
if (test.getStatus() == TestStatus.RUNNING) {
final ITestResult result = IRuntimeFactory.eINSTANCE.createTestResult();
result.setStatus(TestStatus.ERROR);
result.setMessage(executionResult.getException().getMessage());
if (fScriptEngine instanceof IDebugEngine)
result.setStackTrace(((IDebugEngine) fScriptEngine).getExceptionStackTrace());
test.getResults().add(result);
test.setEntityStatus(TestStatus.FINISHED);
} else {
// error in global scope
getTest(ITestEntity.GLOBAL_SCOPE_TEST).addError(executionResult.getException().getMessage(), fScriptEngine);
}
} else {
// error in global scope
getTest(ITestEntity.GLOBAL_SCOPE_TEST).addError(executionResult.getException().getMessage(), fScriptEngine);
}
}
// now check if there were any tests included. If not use testrunner to launch tests
if (getChildren().isEmpty()) {
// load service directly to allow to work in headless mode
final IScriptService scriptService = ScriptService.getInstance();
final ScriptType scriptType = scriptService.getScriptType(getResource().toString());
// TODO check if we can have a smarter binding than a string constant
if (scriptType.getName().equals("JavaScript")) {
if (!fScriptEngine.hasVariable("__EASE_UnitTest_TestRunner")) {
// load the unittest runner
try {
final URL url = new URL("platform:/plugin/org.eclipse.ease.lang.unittest/resources/testrunner/testrunner.JavaScript");
executionResult = fScriptEngine.executeSync(url);
if (executionResult.hasException())
getTest("[EASE Testrunner]").addError(executionResult.getException().getMessage(), fScriptEngine);
} catch (final MalformedURLException e) {
getTest("[EASE Testrunner]").addError(e.getMessage(), fScriptEngine);
}
}
}
}
}
} catch (final InterruptedException e) {
getTest("[user event]").addError("Test aborted by user", fScriptEngine);
} finally {
// testfile teardown
if ((!hasError()) || ((getTestSuite().getDefinition() != null) && (getTestSuite().getDefinition().getFlag(Flag.RUN_TEARDOWN_ON_ERROR, true))))
runSetupTeardownCode(ITestSuiteDefinition.CODE_LOCATION_TESTFILE_TEARDOWN);
// make sure all tests are marked as finished (cleanup for badly written tests from users)
for (final ITestEntity test : getChildren()) {
if (TestStatus.RUNNING.equals(test.getStatus()))
test.setEntityStatus(TestStatus.PASS);
}
fScriptEngine.terminate();
fScriptEngine = null;
setEntityStatus(TestStatus.FINISHED);
if (TestStatus.FINISHED.equals(getStatus()))
setEntityStatus(TestStatus.PASS);
}
} else {
getTest("[Setup]").addError("No engine found for <" + getResource().toString() + ">", null);
}
}
/**
* @generated NOT
*/
private void runSetupTeardownCode(String codeLocation) {
final ITestSuiteDefinition definition = getTestSuite().getDefinition();
if (definition != null) {
final ICode customCode = definition.getCustomCode(codeLocation);
if ((customCode != null) && (!customCode.getContent().trim().isEmpty())) {
if (fScriptEngine != null) {
ScriptResult result;
try {
result = fScriptEngine.executeSync(new Script(customCode.getLocation(), customCode.getContent()));
} catch (final InterruptedException e) {
getTest("[user event]").addError("Aborted by user", fScriptEngine);
return;
}
if (result.hasException()) {
getTest("[" + codeLocation + "]").addError(result.getException().getMessage(), fScriptEngine);
return;
}
} else {
getTest("[" + codeLocation + "]").addError("Could not detect setup/teardown engine", null);
return;
}
}
}
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated NOT
*/
@Override
public void setTerminated(boolean newTerminated) {
super.setTerminated(newTerminated);
if (fScriptEngine != null)
fScriptEngine.terminate();
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated NOT
*/
@Override
public void reset() {
// remove single tests
for (final Object child : getChildren().toArray()) {
if (child instanceof ITestClass)
getChildren().remove(child);
}
super.reset();
// disable if set in test suite (needs to be done after super.reset() as wew change the status here)
final ITestSuite testSuite = getTestSuite();
if (testSuite != null) {
final ITestSuiteDefinition definition = getTestSuite().getDefinition();
if (definition != null) {
final IPath path = getFullPath().makeRelativeTo(getTestSuite().getFullPath());
if (definition.getDisabledResources().contains(path.makeAbsolute())) {
// test is disabled
setDisabled("File disabled in testsuite");
}
}
}
}
/**
* @generated NOT
*/
@Override
public long getEstimatedDuration() {
return (TestStatus.DISABLED.equals(getStatus())) ? 0 : super.getEstimatedDuration();
}
} // TestFile