package com.jetbrains.lang.dart.ide.runner.test;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.execution.filters.UrlFilter;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.testframework.TestConsoleProperties;
import com.intellij.execution.testframework.actions.AbstractRerunFailedTestsAction;
import com.intellij.execution.testframework.autotest.ToggleAutoTestAction;
import com.intellij.execution.testframework.sm.SMCustomMessagesParsing;
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
import com.intellij.execution.testframework.sm.runner.OutputToGeneralTestEventsConverter;
import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties;
import com.intellij.execution.testframework.sm.runner.SMTestLocator;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.lang.dart.ide.runner.DartConsoleFilter;
import com.jetbrains.lang.dart.ide.runner.DartRelativePathsConsoleFilter;
import com.jetbrains.lang.dart.ide.runner.base.DartRunConfiguration;
import com.jetbrains.lang.dart.ide.runner.server.DartCommandLineRunningState;
import com.jetbrains.lang.dart.ide.runner.util.DartTestLocationProvider;
import com.jetbrains.lang.dart.sdk.DartSdk;
import com.jetbrains.lang.dart.sdk.DartSdkUtil;
import com.jetbrains.lang.dart.util.DartUrlResolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class DartTestRunningState extends DartCommandLineRunningState {
public static final String DART_FRAMEWORK_NAME = "DartTestRunner";
private static final String RUN_COMMAND = "run";
private static final String TEST_PACKAGE_SPEC = "test";
private static final String EXPANDED_REPORTER_OPTION = "-r json";
public DartTestRunningState(final @NotNull ExecutionEnvironment environment) throws ExecutionException {
super(environment);
}
@Override
@NotNull
public ExecutionResult execute(final @NotNull Executor executor, final @NotNull ProgramRunner runner) throws ExecutionException {
final ProcessHandler processHandler = startProcess();
final ConsoleView consoleView = createConsole(getEnvironment());
consoleView.attachToProcess(processHandler);
final DefaultExecutionResult executionResult =
new DefaultExecutionResult(consoleView, processHandler, createActions(consoleView, processHandler, executor));
if (ActionManager.getInstance().getAction("RerunFailedTests") != null) {
DartConsoleProperties properties = (DartConsoleProperties)((SMTRunnerConsoleView)consoleView).getProperties();
AbstractRerunFailedTestsAction rerunFailedTestsAction = properties.createRerunFailedTestsAction(consoleView);
assert rerunFailedTestsAction != null;
rerunFailedTestsAction.setModelProvider(((SMTRunnerConsoleView)consoleView)::getResultsViewer);
executionResult.setRestartActions(rerunFailedTestsAction, new ToggleAutoTestAction());
}
else {
executionResult.setRestartActions(new ToggleAutoTestAction());
}
return executionResult;
}
private static ConsoleView createConsole(@NotNull ExecutionEnvironment env) {
final Project project = env.getProject();
final DartRunConfiguration runConfiguration = (DartRunConfiguration)env.getRunProfile();
final DartTestRunnerParameters runnerParameters = (DartTestRunnerParameters)runConfiguration.getRunnerParameters();
final TestConsoleProperties testConsoleProperties = new DartConsoleProperties(runConfiguration, env);
final ConsoleView consoleView = SMTestRunnerConnectionUtil.createConsole(DART_FRAMEWORK_NAME, testConsoleProperties);
try {
final VirtualFile dartFile = runnerParameters.getDartFileOrDirectory();
consoleView.addMessageFilter(new DartConsoleFilter(project, dartFile));
consoleView.addMessageFilter(new DartRelativePathsConsoleFilter(project, runnerParameters.computeProcessWorkingDirectory(project)));
consoleView.addMessageFilter(new UrlFilter());
}
catch (RuntimeConfigurationError ignore) {/* can't happen because already checked */}
Disposer.register(project, consoleView);
return consoleView;
}
@NotNull
@Override
protected ProcessHandler startProcess() throws ExecutionException {
Project project = getEnvironment().getProject();
DartSdk sdk = DartSdk.getDartSdk(project);
if (sdk == null) throw new ExecutionException("Dart SDK cannot be found"); // can't happen, already checked
DartTestRunnerParameters params = getParameters();
StringBuilder builder = new StringBuilder();
builder.append(RUN_COMMAND);
final boolean projectWithoutPubspec = Registry.is("dart.projects.without.pubspec", false);
final String targetName = params.getTargetName();
final String testRunnerOptions = params.getTestRunnerOptions();
if (projectWithoutPubspec &&
params.getScope() == DartTestRunnerParameters.Scope.FOLDER &&
targetName != null &&
!targetName.isEmpty()) {
builder.append(" ").append(":").append(targetName).append(" ").append(EXPANDED_REPORTER_OPTION);
if (testRunnerOptions != null && !testRunnerOptions.isEmpty()) {
builder.append(" ").append(testRunnerOptions);
}
}
else {
builder.append(' ').append(TEST_PACKAGE_SPEC);
builder.append(' ').append(EXPANDED_REPORTER_OPTION);
if (testRunnerOptions != null && !testRunnerOptions.isEmpty()) {
builder.append(" ").append(testRunnerOptions);
}
builder.append(' ').append(params.getFilePath());
if (params.getScope() == DartTestRunnerParameters.Scope.GROUP_OR_TEST_BY_NAME) {
builder.append(" -N \"").append(StringUtil.notNullize(params.getTestName())).append("\"");
}
if (params.getScope() == DartTestRunnerParameters.Scope.MULTIPLE_NAMES) {
final String regex = StringUtil.notNullize(params.getTestName());
// may be empty only in case of Rerun Failed Tests when there are no failed ones yet
if (regex.isEmpty()) {
throw new ExecutionException("No tests to run");
}
builder.append(" -n \"").append(regex).append("\"");
}
}
params.setArguments(builder.toString());
params.setCheckedMode(false);
// working directory is not configurable in UI because there's only one valid value that we calculate ourselves
params.setWorkingDirectory(params.computeProcessWorkingDirectory(project));
return doStartProcess(DartSdkUtil.getPubSnapshotPath(sdk));
}
DartTestRunnerParameters getParameters() {
return (DartTestRunnerParameters)myRunnerParameters;
}
private static class DartConsoleProperties extends SMTRunnerConsoleProperties implements SMCustomMessagesParsing {
public DartConsoleProperties(DartRunConfiguration runConfiguration, ExecutionEnvironment env) {
super(runConfiguration, DART_FRAMEWORK_NAME, env.getExecutor());
setUsePredefinedMessageFilter(false);
setIdBasedTestTree(true);
}
@Nullable
@Override
public SMTestLocator getTestLocator() {
return DartTestLocationProvider.INSTANCE;
}
@Override
public OutputToGeneralTestEventsConverter createTestEventsConverter(@NotNull String testFrameworkName,
@NotNull TestConsoleProperties consoleProperties) {
final DartRunConfiguration runConfiguration = (DartRunConfiguration)getConfiguration();
try {
final VirtualFile file = runConfiguration.getRunnerParameters().getDartFileOrDirectory();
return new DartTestEventsConverter(testFrameworkName, consoleProperties, DartUrlResolver.getInstance(getProject(), file));
}
catch (RuntimeConfigurationError error) {
throw new RuntimeException(error); // can't happen, already checked
}
}
@Nullable
@Override
public AbstractRerunFailedTestsAction createRerunFailedTestsAction(ConsoleView consoleView) {
if (ActionManager.getInstance().getAction("RerunFailedTests") == null) return null; // backward compatibility
DartTestRerunnerAction action = new DartTestRerunnerAction(consoleView);
action.init(this);
return action;
}
}
}