/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation 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 * * Contributors: * IBM Corporation - initial API and implementation * Brock Janiczak (brockj@tpg.com.au) * - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102236: [JUnit] display execution time next to each test *******************************************************************************/ package org.phpsrc.eclipse.pti.tools.phpunit.core.model; import org.eclipse.core.runtime.Assert; public abstract class TestElement implements ITestElement { public final static class Status { public static final Status RUNNING_ERROR = new Status( "RUNNING_ERROR", 5); //$NON-NLS-1$ public static final Status RUNNING_FAILURE = new Status( "RUNNING_FAILURE", 6); //$NON-NLS-1$ public static final Status RUNNING = new Status("RUNNING", 3); //$NON-NLS-1$ public static final Status ERROR = new Status( "ERROR", /* 1 */ITestRunListener.STATUS_ERROR); //$NON-NLS-1$ public static final Status FAILURE = new Status( "FAILURE", /* 2 */ITestRunListener.STATUS_FAILURE); //$NON-NLS-1$ public static final Status OK = new Status( "OK", /* 0 */ITestRunListener.STATUS_OK); //$NON-NLS-1$ public static final Status NOT_RUN = new Status("NOT_RUN", 4); //$NON-NLS-1$ private static final Status[] OLD_CODE = { OK, ERROR, FAILURE }; private final String fName; private final int fOldCode; private Status(String name, int oldCode) { fName = name; fOldCode = oldCode; } public int getOldCode() { return fOldCode; } public String toString() { return fName; } /* error state predicates */ public boolean isOK() { return this == OK || this == RUNNING || this == NOT_RUN; } public boolean isFailure() { return this == FAILURE || this == RUNNING_FAILURE; } public boolean isError() { return this == ERROR || this == RUNNING_ERROR; } public boolean isErrorOrFailure() { return isError() || isFailure(); } /* progress state predicates */ public boolean isNotRun() { return this == NOT_RUN; } public boolean isRunning() { return this == RUNNING || this == RUNNING_FAILURE || this == RUNNING_ERROR; } public boolean isDone() { return this == OK || this == FAILURE || this == ERROR; } public static Status combineStatus(Status one, Status two) { Status progress = combineProgress(one, two); Status error = combineError(one, two); return combineProgressAndErrorStatus(progress, error); } private static Status combineProgress(Status one, Status two) { if (one.isNotRun() && two.isNotRun()) return NOT_RUN; else if (one.isDone() && two.isDone()) return OK; else if (!one.isRunning() && !two.isRunning()) return OK; // one done, one not-run -> a parent failed and its // children are not run else return RUNNING; } private static Status combineError(Status one, Status two) { if (one.isError() || two.isError()) return ERROR; else if (one.isFailure() || two.isFailure()) return FAILURE; else return OK; } private static Status combineProgressAndErrorStatus(Status progress, Status error) { if (progress.isDone()) { if (error.isError()) return ERROR; if (error.isFailure()) return FAILURE; return OK; } if (progress.isNotRun()) { // Assert.isTrue(!error.isErrorOrFailure()); return NOT_RUN; } // Assert.isTrue(progress.isRunning()); if (error.isError()) return RUNNING_ERROR; if (error.isFailure()) return RUNNING_FAILURE; // Assert.isTrue(error.isOK()); return RUNNING; } /** * @param oldStatus * one of {@link ITestRunListener}'s STATUS_* constants * @return the Status */ public static Status convert(int oldStatus) { return OLD_CODE[oldStatus]; } public Result convertToResult() { if (isNotRun()) return Result.UNDEFINED; if (isError()) return Result.ERROR; if (isFailure()) return Result.FAILURE; if (isRunning()) { return Result.UNDEFINED; } return Result.OK; } public ProgressState convertToProgressState() { if (isRunning()) { return ProgressState.RUNNING; } if (isDone()) { return ProgressState.COMPLETED; } return ProgressState.NOT_STARTED; } } private final TestSuiteElement fParent; private final String fId; private String fTestName; private Status fStatus; private String fTrace; private String fExpected; private String fActual; /** * Running time in seconds. Contents depend on the current * {@link #getProgressState()}: * <ul> * <li> * {@link org.eclipse.jdt.junit.model.ITestElement.ProgressState#NOT_STARTED}: {@link Double#NaN}</li> * <li> * {@link org.eclipse.jdt.junit.model.ITestElement.ProgressState#RUNNING}: * negated start time</li> * <li> * {@link org.eclipse.jdt.junit.model.ITestElement.ProgressState#STOPPED}: * elapsed time</li> * <li> * {@link org.eclipse.jdt.junit.model.ITestElement.ProgressState#COMPLETED}: * elapsed time</li> * </ul> */ /* default */double fTime = Double.NaN; /** * @param parent * the parent, can be <code>null</code> * @param id * the test id * @param testName * the test name */ public TestElement(TestSuiteElement parent, String id, String testName) { Assert.isNotNull(id); Assert.isNotNull(testName); fParent = parent; fId = id; fTestName = testName; fStatus = Status.NOT_RUN; if (parent != null) parent.addChild(this); } public ProgressState getProgressState() { return getStatus().convertToProgressState(); } public Result getTestResult(boolean includeChildren) { return getStatus().convertToResult(); } public ITestRunSession getTestRunSession() { return getRoot().getTestRunSession(); } public ITestElementContainer getParentContainer() { if (fParent instanceof TestRoot) { return getTestRunSession(); } return fParent; } public FailureTrace getFailureTrace() { Result testResult = getTestResult(false); if (testResult == Result.ERROR || testResult == Result.FAILURE) { return new FailureTrace(fTrace, fExpected, fActual); } return null; } /** * @return the parent suite, or <code>null</code> for the root */ public TestSuiteElement getParent() { return fParent; } public String getId() { return fId; } public String getTestName() { return fTestName; } public void setName(String name) { fTestName = name; } public void setStatus(Status status) { if (status == Status.RUNNING) { fTime = -System.currentTimeMillis() / 1000d; } else if (status.convertToProgressState() == ProgressState.COMPLETED) { if (fTime < 0) { // assert ! Double.isNaN(fTime) double endTime = System.currentTimeMillis() / 1000.0d; fTime = endTime + fTime; } } fStatus = status; TestSuiteElement parent = getParent(); if (parent != null) parent.childChangedStatus(this, status); } public void setStatus(Status status, String trace, String expected, String actual) { if (trace != null && fTrace != null) { // don't overwrite first trace if same test run logs multiple errors fTrace = fTrace + trace; } else { fTrace = trace; fExpected = expected; fActual = actual; } setStatus(status); } public Status getStatus() { return fStatus; } public String getTrace() { return fTrace; } public String getExpected() { return fExpected; } public String getActual() { return fActual; } public boolean isComparisonFailure() { return fExpected != null && fActual != null; } /** * @return return the class name * @see org.eclipse.jdt.internal.junit.runner.ITestIdentifier#getName() * @see org.eclipse.jdt.internal.junit.runner.MessageIds#TEST_IDENTIFIER_MESSAGE_FORMAT */ public String getClassName() { return extractClassName(getTestName()); } private static String extractClassName(String testNameString) { testNameString = extractRawClassName(testNameString); testNameString = testNameString.replace('$', '.'); // see bug 178503 int index = testNameString.indexOf("::"); if (index > 0) return testNameString.substring(0, index); return testNameString; } public static String extractRawClassName(String testNameString) { int index = testNameString.indexOf('('); if (index < 0) return testNameString; testNameString = testNameString.substring(index + 1); testNameString = testNameString.substring(0, testNameString.indexOf(')')); return testNameString; } public TestRoot getRoot() { return getParent().getRoot(); } public void setElapsedTimeInSeconds(double time) { fTime = time; } public double getElapsedTimeInSeconds() { if (Double.isNaN(fTime) || fTime < 0.0d) { return Double.NaN; } return fTime; } public String toString() { return getProgressState() + " - " + getTestResult(true); //$NON-NLS-1$ } }