/*
* Copyright 2016 Nokia Solutions and Networks
* Licensed under the Apache License, Version 2.0,
* see license.txt file for details.
*/
package org.robotframework.ide.eclipse.main.plugin.launch.tabs;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.rf.ide.core.executor.RobotRuntimeEnvironment;
import org.robotframework.ide.eclipse.main.plugin.RedPlugin;
import org.robotframework.ide.eclipse.main.plugin.launch.IRobotLaunchConfiguration;
import org.robotframework.ide.eclipse.main.plugin.launch.local.RobotLaunchConfiguration;
import org.robotframework.ide.eclipse.main.plugin.launch.remote.RemoteRobotLaunchConfiguration;
import org.robotframework.ide.eclipse.main.plugin.model.RobotCase;
import org.robotframework.ide.eclipse.main.plugin.model.RobotCasesSection;
import org.robotframework.ide.eclipse.main.plugin.model.RobotModel;
import org.robotframework.ide.eclipse.main.plugin.model.RobotModelManager;
import org.robotframework.ide.eclipse.main.plugin.model.RobotProject;
import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile;
import com.google.common.annotations.VisibleForTesting;
/**
* @author Michal Anglart
*/
class LaunchConfigurationTabValidator {
private final RobotModel model;
LaunchConfigurationTabValidator() {
this(RedPlugin.getModelManager().getModel());
}
@VisibleForTesting
LaunchConfigurationTabValidator(final RobotModel model) {
this.model = model;
}
void validateRobotTab(final RobotLaunchConfiguration robotConfig)
throws LaunchConfigurationValidationException, LaunchConfigurationValidationFatalException {
try {
final List<String> warnings = new ArrayList<>();
try {
robotConfig.getProject();
} catch (final CoreException e) {
throw new LaunchConfigurationValidationFatalException(e.getStatus().getMessage());
}
final Map<IResource, List<String>> suitesToRun = robotConfig.collectSuitesToRun();
if (suitesToRun.isEmpty()) {
warnings.add("There are no suites specified. All suites in '" + robotConfig.getProjectName()
+ "' will be executed.");
}
validateSuitesToRun(suitesToRun);
if (!warnings.isEmpty()) {
throw new LaunchConfigurationValidationException(String.join("\n", warnings));
}
} catch (final CoreException e) {
throw new LaunchConfigurationValidationFatalException(
"Run configuration '" + robotConfig.getName() + "' contains problems: " + e.getMessage(), e);
}
}
void validateListenerTab(final IRobotLaunchConfiguration robotConfig)
throws LaunchConfigurationValidationFatalException {
try {
if (robotConfig instanceof RemoteRobotLaunchConfiguration) {
robotConfig.getProject();
}
if (robotConfig.isUsingRemoteAgent()) {
robotConfig.getAgentConnectionHost();
robotConfig.getAgentConnectionPort();
robotConfig.getAgentConnectionTimeout();
}
} catch (final CoreException e) {
throw new LaunchConfigurationValidationFatalException(e.getStatus().getMessage());
}
}
void validateExecutorTab(final RobotLaunchConfiguration robotConfig)
throws LaunchConfigurationValidationException, LaunchConfigurationValidationFatalException {
try {
final List<String> warnings = new ArrayList<>();
final String projectName = robotConfig.getProjectName();
if (robotConfig.isUsingInterpreterFromProject()) {
validateRuntimeEnvironment(projectName);
} else {
warnings.add("Tests will be launched using '" + robotConfig.getInterpreter().name()
+ "' interpreter as defined in PATH environment variable");
}
validateExecutableFile(robotConfig.getExecutableFilePath());
if (!warnings.isEmpty()) {
throw new LaunchConfigurationValidationException(String.join("\n", warnings));
}
} catch (final CoreException e) {
throw new LaunchConfigurationValidationFatalException(
"Run configuration '" + robotConfig.getName() + "' contains problems: " + e.getMessage(), e);
}
}
private void validateRuntimeEnvironment(final String projectName) {
if (!projectName.isEmpty()) {
final IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
final RobotProject robotProject = model.createRobotProject(project);
final RobotRuntimeEnvironment env = robotProject.getRuntimeEnvironment();
if (env == null || !env.isValidPythonInstallation()) {
throw new LaunchConfigurationValidationFatalException(
"Project '" + projectName + "' is using invalid Python environment");
} else if (!env.hasRobotInstalled()) {
throw new LaunchConfigurationValidationFatalException(
"Project '" + projectName + "' is using invalid Python environment (missing Robot Framework)");
}
}
}
private void validateExecutableFile(final String filePath) {
if (!filePath.isEmpty()) {
final File file = new File(filePath);
if (!file.exists()) {
throw new LaunchConfigurationValidationFatalException("Executable file does not exist");
}
}
}
private void validateSuitesToRun(final Map<IResource, List<String>> suitesToRun) {
final List<String> problematicSuites = new ArrayList<>();
final List<String> problematicTests = new ArrayList<>();
for (final IResource resource : suitesToRun.keySet()) {
if (!resource.exists()) {
problematicSuites.add(resource.getFullPath().toString());
} else if (resource.getType() == IResource.FILE) {
final RobotSuiteFile suiteModel = RobotModelManager.getInstance().createSuiteFile((IFile) resource);
final List<RobotCase> cases = new ArrayList<>();
final Optional<RobotCasesSection> section = suiteModel.findSection(RobotCasesSection.class);
if (section.isPresent()) {
cases.addAll(section.get().getChildren());
}
for (final String caseName : suitesToRun.get(resource)) {
boolean exist = false;
for (final RobotCase test : cases) {
if (test.getName().equalsIgnoreCase(caseName)) {
exist = true;
break;
}
}
if (!exist) {
problematicTests.add(caseName);
}
}
}
}
if (!problematicSuites.isEmpty()) {
throw new LaunchConfigurationValidationFatalException(
"Following suites does not exist: " + String.join(", ", problematicSuites));
}
if (!problematicTests.isEmpty()) {
throw new LaunchConfigurationValidationFatalException(
"Following tests does not exist: " + String.join(", ", problematicTests));
}
}
class LaunchConfigurationValidationException extends RuntimeException {
private static final long serialVersionUID = 1L;
public LaunchConfigurationValidationException(final String message) {
super(message);
}
}
class LaunchConfigurationValidationFatalException extends RuntimeException {
private static final long serialVersionUID = 1L;
public LaunchConfigurationValidationFatalException(final String message) {
super(message);
}
public LaunchConfigurationValidationFatalException(final String message, final Exception e) {
super(message, e);
}
}
}