ConcurrentModificationException in SM Runner fixed
[fedora-idea.git] / smRunner / src / com / intellij / execution / testframework / sm / SMTestRunnerConnectionUtil.java
blobac58c015c6db02534bcf1dc9b7368b952a10e752
1 package com.intellij.execution.testframework.sm;
3 import com.intellij.execution.ExecutionException;
4 import com.intellij.execution.configurations.CommandLineState;
5 import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
6 import com.intellij.execution.configurations.RunnerSettings;
7 import com.intellij.execution.configurations.RuntimeConfiguration;
8 import com.intellij.execution.process.ProcessAdapter;
9 import com.intellij.execution.process.ProcessEvent;
10 import com.intellij.execution.process.ProcessHandler;
11 import com.intellij.execution.testframework.TestConsoleProperties;
12 import com.intellij.execution.testframework.sm.runner.GeneralToSMTRunnerEventsConvertor;
13 import com.intellij.execution.testframework.sm.runner.OutputToGeneralTestEventsConverter;
14 import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties;
15 import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
16 import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerUIActionsHandler;
17 import com.intellij.execution.testframework.sm.runner.ui.SMTestRunnerResultsForm;
18 import com.intellij.execution.testframework.sm.runner.ui.statistics.StatisticsPanel;
19 import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
20 import com.intellij.execution.ui.ConsoleView;
21 import com.intellij.openapi.util.Disposer;
22 import com.intellij.openapi.util.Key;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
26 /**
27 * @author Roman Chernyatchik
29 public class SMTestRunnerConnectionUtil {
30 private SMTestRunnerConnectionUtil() {
31 // Do nothing. Utility class.
34 /**
35 * Creates Test Runner console component with test tree, console, statistics tabs
36 * and attaches it to given Process handler.
38 * You can use this method in run configuration's CommandLineState. You should
39 * just override "execute" method of your custom command line state and return
40 * test runner's console.
42 * @param processHandler Process handler
43 * @param consoleProperties Console properties for test console actions
44 * @return Console view
45 * @throws ExecutionException If IDEA cannot execute process this Exception will
46 * be catched and shown in error message box
48 public static BaseTestsOutputConsoleView attachRunner(@NotNull final ProcessHandler processHandler,
49 final TestConsoleProperties consoleProperties,
50 final RunnerSettings runnerSettings,
51 final ConfigurationPerRunnerSettings configurationSettings,
52 final String splitterPropertyName) throws ExecutionException {
54 // Console
55 final SMTRunnerConsoleView testRunnerConsole = new SMTRunnerConsoleView(consoleProperties, runnerSettings, configurationSettings, splitterPropertyName);
56 testRunnerConsole.initUI();
57 final SMTestRunnerResultsForm resultsViewer = testRunnerConsole.getResultsViewer();
59 // attach listeners
60 attachEventsProcessors(consoleProperties, resultsViewer, resultsViewer.getStatisticsPane(), processHandler);
61 testRunnerConsole.attachToProcess(processHandler);
63 return testRunnerConsole;
66 /**
67 * Creates Test Runner console component with test tree, console, statistics tabs
68 * and attaches it to given Process handler.
70 * You can use this method in run configuration's CommandLineState. You should
71 * just override "execute" method of your custom command line state and return
72 * test runner's console.
74 * E.g:
75 * <code>
76 * public class MyCommandLineState extends CommandLineState {
78 * // ...
80 * @Override
81 * public ExecutionResult execute(@NotNull final Executor executor,
82 * @NotNull final ProgramRunner runner) throws ExecutionException {
84 * final ProcessHandler processHandler = startProcess();
85 * final AbstractRubyRunConfiguration runConfiguration = getConfig();
86 * final Project project = runConfiguration.getProject();
88 * final ConsoleView console =
89 * SMTestRunnerConnectionUtil.attachRunner(project, processHandler, this, runConfiguration,
90 * "MY_TESTRUNNER_SPLITTER_SETTINGS");
92 * return new DefaultExecutionResult(console, processHandler,
93 * createActions(console, processHandler));
94 * }
95 * }
96 * </code>
98 * @param processHandler Process handler
99 * @param commandLineState Command line state
100 * @param config User run configuration settings
101 * @param splitterPropertyName This property will be used for storing splitter position.
102 * @return Console view
103 * @throws ExecutionException If IDEA cannot execute process this Exception will
104 * be catched and shown in error message box
106 public static ConsoleView attachRunner(@NotNull final ProcessHandler processHandler,
107 @NotNull final CommandLineState commandLineState,
108 @NotNull final RuntimeConfiguration config,
109 @Nullable final String splitterPropertyName) throws ExecutionException {
110 final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(config);
112 return attachRunner(processHandler, consoleProperties,
113 commandLineState.getRunnerSettings(), commandLineState.getConfigurationSettings(), splitterPropertyName);
116 private static ProcessHandler attachEventsProcessors(final TestConsoleProperties consoleProperties,
117 final SMTestRunnerResultsForm resultsViewer,
118 final StatisticsPanel statisticsPane,
119 final ProcessHandler processHandler)
120 throws ExecutionException {
122 //build messages consumer
123 final OutputToGeneralTestEventsConverter outputConsumer = new OutputToGeneralTestEventsConverter();
125 //events processor
126 final GeneralToSMTRunnerEventsConvertor eventsProcessor = new GeneralToSMTRunnerEventsConvertor(resultsViewer.getTestsRootNode());
128 //ui actions
129 final SMTRunnerUIActionsHandler uiActionsHandler = new SMTRunnerUIActionsHandler(consoleProperties);
131 // subscribe on events
133 // subsrcibes event processor on output consumer events
134 outputConsumer.setProcessor(eventsProcessor);
135 // subsrcibes result viewer on event processor
136 eventsProcessor.addEventsListener(resultsViewer);
137 // subsrcibes test runner's actions on results viewer events
138 resultsViewer.addEventsListener(uiActionsHandler);
139 // subsrcibes statistics tab viewer on event processor
140 eventsProcessor.addEventsListener(statisticsPane.createTestEventsListener());
142 processHandler.addProcessListener(new ProcessAdapter() {
143 @Override
144 public void processTerminated(final ProcessEvent event) {
145 Disposer.dispose(eventsProcessor);
146 Disposer.dispose(outputConsumer);
149 @Override
150 public void startNotified(final ProcessEvent event) {
151 eventsProcessor.onStartTesting();
154 @Override
155 public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
156 outputConsumer.flushBufferBeforeTerminating();
157 eventsProcessor.onFinishTesting();
160 @Override
161 public void onTextAvailable(final ProcessEvent event, final Key outputType) {
162 outputConsumer.process(event.getText(), outputType);
165 return processHandler;