/*******************************************************************************
* Copyright Technophobia Ltd 2012
*
* This file is part of the Substeps Eclipse Plugin.
*
* The Substeps Eclipse Plugin is free software: you can redistribute it and/or modify
* it under the terms of the Eclipse Public License v1.0.
*
* The Substeps Eclipse Plugin 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
* Eclipse Public License for more details.
*
* You should have received a copy of the Eclipse Public License
* along with the Substeps Eclipse Plugin. If not, see <http://www.eclipse.org/legal/epl-v10.html>.
******************************************************************************/
package com.technophobia.substeps.model.structure;
import java.util.ArrayList;
import java.util.List;
public class DefaultSubstepsTestParentElement extends AbstractSubstepsTestElement implements SubstepsTestParentElement {
private final List<SubstepsTestElement> children;
private Status childrenStatus;
private final int testCount;
public DefaultSubstepsTestParentElement(final SubstepsTestParentElement parent, final String id,
final String testName, final int testCount) {
super(parent, id, testName);
this.testCount = testCount;
this.children = new ArrayList<SubstepsTestElement>(testCount);
this.childrenStatus = Status.NOT_RUN;
}
@Override
public Result getTestResult(final boolean includeChildren) {
if (includeChildren) {
return getStatus().asResult();
}
return super.getStatus().asResult();
}
@Override
public int getChildCount() {
return testCount;
}
@Override
public SubstepsTestElement[] getChildren() {
return children.toArray(new SubstepsTestElement[children.size()]);
}
@Override
public void addChild(final SubstepsTestElement child) {
children.add(child);
}
@Override
public Status getStatus() {
final Status suiteStatus = getSuiteStatus();
if (!childrenStatus.equals(Status.NOT_RUN)) {
return Status.combineStatus(childrenStatus, suiteStatus);
}
return suiteStatus;
}
@Override
public void childChangedStatus(final SubstepsTestElement child, final Status childStatus) {
if (isFirstChild(child) && childStatus.isRunning()) {
// is 1st child, and is running, so copy status
updateTimeAndChildrenStatus(childStatus);
return;
}
final SubstepsTestElement lastChild = children.get(getChildCount() - 1);
if (child == lastChild) {
if (childStatus.isComplete()) {
// all children done, collect cumulative status
updateTimeAndChildrenStatus(getCumulatedStatus());
return;
}
} else if (!lastChild.getStatus().isNotRun()) {
// child is not last, but last child has been run - child has been
// rerun or is rerunning
updateTimeAndChildrenStatus(getCumulatedStatus());
return;
}
// finally, set RUNNING_FAILURE/ERROR if child has failed but suite has
// not failed
if (childStatus.isFailure()) {
if (!childrenStatus.isErrorOrFailure()) {
updateTimeAndChildrenStatus(Status.RUNNING_FAILURE);
return;
}
} else if (childStatus.isError()) {
if (!childrenStatus.isError()) {
updateTimeAndChildrenStatus(Status.RUNNING_ERROR);
return;
}
}
}
private boolean isFirstChild(final SubstepsTestElement child) {
return !children.isEmpty() && children.get(0) == child;
}
private void updateTimeAndChildrenStatus(final Status status) {
if (childrenStatus.equals(status)) {
return;
}
if (status.equals(Status.RUNNING)) {
if (time >= 0.0d) {
// re-running child - ignore
} else {
time = -System.currentTimeMillis() / 1000.0d;
}
} else if (status.isComplete()) {
if (time < 0) {
final double endTime = System.currentTimeMillis() / 1000.0d;
time = endTime + time;
}
}
this.childrenStatus = status;
final SubstepsTestParentElement parent = getParent();
if (parent != null) {
parent.childChangedStatus(this, getStatus());
}
}
private Status getCumulatedStatus() {
// copy list to avoid concurrency problems
final SubstepsTestElement[] childTestElements = this.children.toArray(new SubstepsTestElement[this.children
.size()]);
if (childTestElements.length == 0)
return getSuiteStatus();
Status cumulated = childTestElements[0].getStatus();
for (int i = 1; i < childTestElements.length; i++) {
final Status childStatus = childTestElements[i].getStatus();
cumulated = Status.combineStatus(cumulated, childStatus);
}
// not necessary, see special code in Status.combineProgress()
// if (suiteStatus.isErrorOrFailure() && cumulated.isNotRun())
// return suiteStatus; //progress is Done if error in Suite and no
// children run
return cumulated;
}
private Status getSuiteStatus() {
return super.getStatus();
}
}