2 * Copyright 2000-2007 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.intellij
.execution
.junit2
;
19 import com
.intellij
.execution
.Location
;
20 import com
.intellij
.execution
.junit2
.info
.TestInfo
;
21 import com
.intellij
.execution
.junit2
.segments
.InputConsumer
;
22 import com
.intellij
.execution
.junit2
.states
.Statistics
;
23 import com
.intellij
.execution
.junit2
.states
.TestState
;
24 import com
.intellij
.execution
.testframework
.*;
25 import com
.intellij
.execution
.testframework
.ui
.PrintableTestProxy
;
26 import com
.intellij
.execution
.ui
.ConsoleViewContentType
;
27 import com
.intellij
.openapi
.diagnostic
.Logger
;
28 import com
.intellij
.openapi
.project
.Project
;
29 import com
.intellij
.pom
.Navigatable
;
30 import org
.jetbrains
.annotations
.NotNull
;
32 import java
.util
.ArrayList
;
33 import java
.util
.Collections
;
34 import java
.util
.Iterator
;
35 import java
.util
.List
;
37 public class TestProxy
extends CompositePrintable
implements PrintableTestProxy
, InputConsumer
, ChangingPrintable
, TestProxyParent
{
38 private static final Logger LOG
= Logger
.getInstance("#com.intellij.execution.junit2.TestProxy");
40 private final TestInfo myInfo
;
41 private TestState myState
= TestState
.DEFAULT
;
42 private Printer myPrinter
= Printer
.DEAF
;
43 private final TestProxyListenersNotifier myNotifier
= new TestProxyListenersNotifier();
44 private Statistics myStatistics
= new Statistics();
45 private TestEventsConsumer myEventsConsumer
;
46 private int myPreviousMagnitude
= -1;
47 private int myStateTimestamp
= 0;
48 private boolean myMarked
= false;
50 // private ArrayList myChildren = new ArrayList();
51 private final FilterCache myChildren
= new FilterCache();
52 private TestProxy myParent
= null;
54 public TestProxy(@NotNull final TestInfo info
) {
58 public String
toString() {
59 return getInfo().getComment() + "." + getInfo().getName();
62 public void onOutput(final String text
, final ConsoleViewContentType contentType
) {
63 if (!myMarked
&& contentType
== ConsoleViewContentType
.ERROR_OUTPUT
) {
67 final ExternalOutput printable
= new ExternalOutput(text
, contentType
);
71 public void addLast(final Printable printable
) {
72 super.addLast(printable
);
73 fireOnNewPrintable(printable
);
76 private void fireOnNewPrintable(final Printable printable
) {
77 myPrinter
.onNewAvaliable(printable
);
80 public void printOn(final Printer printer
) {
81 super.printOn(printer
);
82 CompositePrintable
.printAllOn(myChildren
.getList(), printer
);
83 myState
.printOn(printer
);
86 public TestState
getState() {
90 public void setState(final TestState state
) {
91 if (myState
!= state
) {
93 fireOnNewPrintable(state
);
98 private void fireStateChanged() {
100 pullEvent(new StateChangedEvent(this));
101 if (myParent
!= null)
102 myParent
.onChanged(this);
103 fireStatisticsChanged();
104 myNotifier
.onChanged(this);
107 public int getStateTimestamp() {
108 return myStateTimestamp
;
111 public TestProxy
getChildAt(final int childIndex
) {
112 return myChildren
.getList().get(childIndex
);
115 public int getChildCount() {
116 return myChildren
.getList().size();
119 public List
<TestProxy
> getChildren() {
120 return myChildren
.getUnmodifiableList();
123 public TestProxy
getParent() {
127 public Navigatable
getDescriptor(final Location location
) {
128 return getState().getDescriptor(location
);
131 public String
getName() {
132 return getInfo().getName();
135 public boolean isInProgress() {
136 return getState().isInProgress();
139 public boolean isDefect() {
140 return getState().isDefect();
143 public boolean shouldRun() {
144 return getInfo().shouldRun();
147 public int getMagnitude() {
148 return getState().getMagnitude();
151 public Location
getLocation(final Project project
) {
152 return getInfo().getLocation(project
);
155 public boolean isLeaf() {
156 return getChildCount() == 0;
159 public void addChild(final TestProxy child
) {
160 if (myChildren
.getList().contains(child
))
162 if (child
.getParent() != null)
163 throw new RuntimeException("Test: "+child
+ " already has parent: " + child
.getParent());
164 myChildren
.add(child
);
165 child
.myParent
= this;
166 if (myPrinter
!= Printer
.DEAF
) {
167 child
.setPrintLinstener(myPrinter
);
168 child
.fireOnNewPrintable(child
);
170 pullEvent(new NewChildEvent(this, child
));
171 fireStatisticsChanged();
172 getState().changeStateAfterAddingChaildTo(this, child
);
173 myNotifier
.onChildAdded(this, child
);
176 public void setPrintLinstener(final Printer printer
) {
178 for (Iterator iterator
= myChildren
.iterator(); iterator
.hasNext();) {
179 final TestProxy testProxy
= (TestProxy
) iterator
.next();
180 testProxy
.setPrintLinstener(printer
);
184 public TestInfo
getInfo() {
188 public void onChildAdded(final AbstractTestProxy parent
, final AbstractTestProxy newChild
) {
189 fireStatisticsChanged();
192 public void onChanged(final AbstractTestProxy test
) {
193 myChildren
.resetCache();
194 final int magnitude
= test
.getMagnitude();
196 if (myPreviousMagnitude
< magnitude
|| getState().getMagnitude() <= magnitude
) {
198 myPreviousMagnitude
= getState().getMagnitude();
202 public void onStatisticsChanged(final AbstractTestProxy testProxy
) {
203 myChildren
.resetCache();
204 fireStatisticsChanged();
207 private void fireStatisticsChanged() {
208 myChildren
.resetCache();
209 if (myParent
!= null)
210 myParent
.onStatisticsChanged(this);
211 pullEvent(new StatisticsChanged(this));
212 myNotifier
.onStatisticsChanged(this);
215 public void addListener(final TestProxyListener listener
) {
216 myNotifier
.addListener(listener
);
219 public void setStatistics(final Statistics statistics
) {
220 myChildren
.resetCache();
221 if (!myState
.isFinal()) {
222 LOG
.error("" + myState
.getMagnitude());
224 myStatistics
= statistics
;
225 fireStatisticsChanged();
228 public Statistics
getStatisticsImpl() {
232 public boolean hasChildSuites() {
233 return myChildren
.detect(Filter
.NOT_LEAF
) != null;
236 public Statistics
getStatistics() {
237 return myState
.getStatisticsFor(this);
240 public TestProxy
[] selectChildren(final Filter filter
) {
241 return myChildren
.select(filter
);
244 public void setEventsConsumer(final TestEventsConsumer eventsConsumer
) {
245 myEventsConsumer
= eventsConsumer
;
248 private void pullEvent(final TestEvent event
) {
249 if (myEventsConsumer
!= null) {
250 myEventsConsumer
.onEvent(event
);
253 if (myParent
!= null)
254 myParent
.pullEvent(event
);
257 public List
<TestProxy
> getAllTests() {
258 return myState
.getAllTestsOf(this);
261 public void collectAllTestsTo(final ArrayList
<TestProxy
> allTests
) {
263 for (Iterator iterator
= myChildren
.iterator(); iterator
.hasNext();) {
264 final TestProxy testProxy
= (TestProxy
) iterator
.next();
265 testProxy
.collectAllTestsTo(allTests
);
269 public TestProxy
getCommonAncestor(final TestProxy test
) {
270 if (test
== null) return this;
271 if (test
.isAncestorOf(this)) return test
;
272 for (TestProxy parent
= this; parent
!= null; parent
= parent
.getParent())
273 if (parent
.isAncestorOf(test
)) return parent
;
277 public boolean isAncestorOf(final TestProxy test
) {
278 if (test
== null) return false;
279 for (TestProxy parent
= test
; parent
!= null; parent
= parent
.getParent())
280 if (parent
== this) return true;
284 public AbstractTestProxy
[] getPathFromRoot() {
285 final ArrayList
<TestProxy
> parents
= new ArrayList
<TestProxy
>();
286 TestProxy test
= this;
289 } while ((test
= test
.getParent()) != null);
290 Collections
.reverse(parents
);
291 return parents
.toArray(new TestProxy
[parents
.size()]);
294 public boolean isRoot() {
295 return getParent() == null;
300 public TestState
.StateInterval
calculateInterval(final SuiteState state
) {
301 final SuiteState
.SuiteStateInterval result
= new SuiteState
.SuiteStateInterval(state
, getChildAt(0).getState().getInterval());
302 for (TestProxy proxy
: getChildren()) {
303 result
.updateFrom(proxy
.getState().getInterval());