/*
* Copyright 2013-2016 consulo.io
*
* 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 consulo.execution.testframework.thrift.runner;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.testframework.TestConsoleProperties;
import com.intellij.execution.testframework.sm.CompositeTestLocationProvider;
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
import com.intellij.execution.testframework.sm.runner.*;
import com.intellij.execution.testframework.sm.runner.ui.AttachToProcessListener;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerUIActionsHandler;
import com.intellij.execution.testframework.sm.runner.ui.SMTestRunnerResultsForm;
import com.intellij.execution.testframework.sm.runner.ui.statistics.StatisticsPanel;
import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.testIntegration.TestLocationProvider;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
/**
* @author VISTALL
* @since 18.05.14
*/
public class ThriftTestExecutionUtil {
public static BaseTestsOutputConsoleView createConsoleWithCustomLocator(@NotNull final String testFrameworkName,
@NotNull final TestConsoleProperties consoleProperties,
@NotNull ExecutionEnvironment environment,
@NotNull ThriftTestHandlerFactory factory,
@Nullable final TestLocationProvider locator) {
return createConsoleWithCustomLocator(testFrameworkName, consoleProperties, environment, locator, factory, null);
}
public static SMTRunnerConsoleView createConsoleWithCustomLocator(@NotNull final String testFrameworkName,
@NotNull final TestConsoleProperties consoleProperties,
ExecutionEnvironment environment,
@Nullable final TestLocationProvider locator,
final ThriftTestHandlerFactory factory,
@Nullable final TestProxyFilterProvider filterProvider) {
String splitterPropertyName = SMTestRunnerConnectionUtil.getSplitterPropertyName(testFrameworkName);
SMTRunnerConsoleView consoleView = new SMTRunnerConsoleView(consoleProperties, splitterPropertyName);
initConsoleView(consoleView, testFrameworkName, locator, factory, filterProvider);
return consoleView;
}
public static void initConsoleView(@NotNull final SMTRunnerConsoleView consoleView,
@NotNull final String testFrameworkName,
@Nullable final TestLocationProvider locator,
final ThriftTestHandlerFactory factory,
@Nullable final TestProxyFilterProvider filterProvider) {
consoleView.addAttachToProcessListener(new AttachToProcessListener() {
@Override
public void onAttachToProcess(@NotNull ProcessHandler processHandler) {
TestProxyPrinterProvider printerProvider = null;
if (filterProvider != null) {
printerProvider = new TestProxyPrinterProvider(consoleView, filterProvider);
}
SMTestRunnerResultsForm resultsForm = consoleView.getResultsViewer();
attachEventsProcessors(consoleView.getProperties(), resultsForm, resultsForm.getStatisticsPane(), processHandler, testFrameworkName, locator, factory,
printerProvider);
}
});
consoleView.setHelpId("reference.runToolWindow.testResultsTab");
consoleView.initUI();
}
private static void attachEventsProcessors(@NotNull final TestConsoleProperties consoleProperties,
final SMTestRunnerResultsForm resultsViewer,
final StatisticsPanel statisticsPane,
final ProcessHandler processHandler,
@NotNull final String testFrameworkName,
@Nullable final com.intellij.testIntegration.TestLocationProvider locator,
ThriftTestHandlerFactory factory,
@Nullable TestProxyPrinterProvider printerProvider) {
//build messages consumer
final OutputToGeneralTestEventsConverter outputConsumer;
outputConsumer = new OutputToGeneralTestEventsConverter(testFrameworkName, consoleProperties);
//events processor
final GeneralTestEventsProcessor eventsProcessor =
new GeneralToSMTRunnerEventsConvertor(consoleProperties.getProject(), resultsViewer.getTestsRootNode(), testFrameworkName);
final TServer open = open(factory.getPort(), factory.createHandler(eventsProcessor));
if (locator != null) {
eventsProcessor.setLocator(new CompositeTestLocationProvider(locator));
}
if (printerProvider != null) {
eventsProcessor.setPrinterProvider(printerProvider);
}
// ui actions
final SMTRunnerUIActionsHandler uiActionsHandler = new SMTRunnerUIActionsHandler(consoleProperties);
// subscribe on events
// subscribes event processor on output consumer events
outputConsumer.setProcessor(eventsProcessor);
// subscribes result viewer on event processor
eventsProcessor.addEventsListener(resultsViewer);
// subscribes test runner's actions on results viewer events
resultsViewer.addEventsListener(uiActionsHandler);
// subscribes statistics tab viewer on event processor
eventsProcessor.addEventsListener(statisticsPane.createTestEventsListener());
processHandler.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(final ProcessEvent event) {
outputConsumer.flushBufferBeforeTerminating();
try {
open.stop();
}
catch (Exception ignored) {
}
eventsProcessor.onFinishTesting();
Disposer.dispose(eventsProcessor);
Disposer.dispose(outputConsumer);
}
@Override
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
outputConsumer.process(event.getText(), outputType);
}
});
}
public static TServer open(int port, TestInterface.Iface iface) {
TServerSocket localhost = null;
try {
localhost = new TServerSocket(new InetSocketAddress("localhost", port));
}
catch (TTransportException e) {
throw new IllegalArgumentException(e);
}
TestInterface.Processor<TestInterface.Iface> processor = new TestInterface.Processor<TestInterface.Iface>(iface);
TSimpleServer server = new TSimpleServer(new TServer.Args(localhost).processor(processor));
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
server.serve();
}
});
return server;
}
public static int getFreePort() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(0);
return serverSocket.getLocalPort();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (serverSocket != null) {
try {
serverSocket.close();
}
catch (IOException e) {
//
}
}
}
throw new IllegalArgumentException("Cant get free port");
}
}