blob: c8c1cdcd89333bc4b1cc4ebdf0308d1b7f718dfc [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed 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
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.execution.junit2.states;
import com.intellij.execution.junit2.TestProxy;
import com.intellij.execution.junit2.TestProxyListener;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.execution.testframework.Printer;
import com.intellij.rt.execution.junit.states.PoolOfTestStates;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SuiteState extends TestState {
private final TestProxy myTest;
private int myMaxMagnitude = PoolOfTestStates.NOT_RUN_INDEX;
private boolean myHasRunning;
private final StateCache myCache = new StateCache();
public SuiteState(final TestProxy test) {
myTest = test;
myTest.addListener(new TestProxyListener() {
public void onChildAdded(final AbstractTestProxy testProxy, final AbstractTestProxy newChild) {
if (newChild.getParent() == myTest) {
myCache.invalidate();
}
}
public void onChanged(final AbstractTestProxy test) {
if (test == myTest) myCache.invalidate();
}
public void onStatisticsChanged(final AbstractTestProxy test) {
if (test == myTest) myCache.invalidate();
}
});
}
public int getMagnitude() {
return myHasRunning ? PoolOfTestStates.RUNNING_INDEX : myMaxMagnitude;
}
public void update() {
myCache.invalidate();
}
public void printOn(final Printer printer) {
}
public boolean isFinal() {
return true;
}
public boolean isDefect() {
return getMagnitude() >= PoolOfTestStates.FAILED_INDEX;
}
public boolean isInProgress() {
return myCache.get(IS_IN_PROGRESS).booleanValue();
}
public Statistics getStatisticsFor(final TestProxy test) {
return myCache.get(GET_STATISTICS);
}
public List<TestProxy> getAllTestsOf(final TestProxy test) {
return myCache.get(ALL_TESTS);
}
public void changeStateAfterAddingChildTo(final TestProxy test, final TestProxy child) {
if (child.getState().getMagnitude() <= getMagnitude()) {
test.onStatisticsChanged();
return;
}
test.onChanged(test);
}
public void setRunning(boolean running) {
myHasRunning = running;
}
public boolean isRunning() {
return myHasRunning;
}
public void updateMagnitude(int magnitude) {
if (myMaxMagnitude == PoolOfTestStates.NOT_RUN_INDEX) {
myMaxMagnitude = magnitude;
} else if (myMaxMagnitude < magnitude) {
myMaxMagnitude = magnitude;
}
}
private static final CachedAcpect<List<TestProxy>> ALL_TESTS = new CachedAcpect<List<TestProxy>>() {
public List<TestProxy> calculate(final SuiteState state) {
final ArrayList<TestProxy> allTests = new ArrayList<TestProxy>();
state.myTest.collectAllTestsTo(allTests);
return allTests;
}
};
private static final CachedAcpect<Statistics> GET_STATISTICS = new CachedAcpect<Statistics>() {
public Statistics calculate(final SuiteState state) {
final CumulativeStatistics result = new CumulativeStatistics();
for (final TestProxy testCase : state.myTest.getChildren()) {
result.add(testCase.getStatistics());
}
return result;
}
};
private static final CachedAcpect<Boolean> IS_IN_PROGRESS = new CachedAcpect<Boolean>() {
public Boolean calculate(final SuiteState state) {
final List<TestProxy> children = state.myTest.getChildren();
for (int i = children.size() - 1; i >= 0; i--) {
if (children.get(i).isInProgress()) return Boolean.TRUE;
}
return Boolean.FALSE;
}
};
private static abstract class CachedAcpect<T> {
private static int ourNextInstanceIndex = 0;
private final int myId;
protected CachedAcpect() {
synchronized (CachedAcpect.class) {
myId = ourNextInstanceIndex;
ourNextInstanceIndex++;
}
}
public abstract T calculate(SuiteState state);
public int getId() {
return myId;
}
}
private class StateCache {
private final Object[] myValues = new Object[3];
public <T> T get(final CachedAcpect<T> aspect) {
final int id = aspect.getId();
T value = (T)myValues[id];
if (value == null) {
value = aspect.calculate(SuiteState.this);
myValues[id] = value;
}
return value;
}
public void invalidate() {
Arrays.fill(myValues, null);
}
}
}