// Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).
package com.twitter.intellij.pants.execution;
import com.intellij.execution.Location;
import com.intellij.execution.PsiLocation;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.ConfigurationFromContext;
import com.intellij.execution.actions.RunConfigurationProducer;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration;
import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.MapDataContext;
import com.twitter.intellij.pants.PantsManager;
import com.twitter.intellij.pants.service.task.PantsTaskManager;
import com.twitter.intellij.pants.settings.PantsExecutionSettings;
import com.twitter.intellij.pants.testFramework.OSSPantsIntegrationTest;
import com.twitter.intellij.pants.util.PantsUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class OSSPantsJvmRunConfigurationIntegrationTest extends OSSPantsIntegrationTest {
public void testClassRunConfiguration() throws Throwable {
doImport("testprojects/tests/java/org/pantsbuild/testproject/testjvms");
String classReference = "org.pantsbuild.testproject.testjvms.TestSix";
PsiClass testClass = JavaPsiFacade.getInstance(myProject).findClass(classReference, GlobalSearchScope.allScope(myProject));
assertNotNull(testClass);
ExternalSystemRunConfiguration esc = getExternalSystemRunConfiguration(testClass);
// Make sure task name is `test` goal.
assertEquals(Collections.singletonList("test"), esc.getSettings().getTaskNames());
List<String> configScriptParameters = PantsUtil.parseCmdParameters(Optional.ofNullable(esc.getSettings().getScriptParameters()));
List<String> expectedConfigScriptParameters = Arrays.asList(
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:eight-test-platform",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:six",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:seven",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:eight",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:base",
"--test-junit-test=" + classReference
);
assertEquals(expectedConfigScriptParameters, configScriptParameters);
// Make sure this configuration does not contain any task before running if added to the project.
assertEmptyBeforeRunTask(esc);
/**
* Check the final command line parameters when config is run, as
* {@link com.twitter.intellij.pants.service.task.PantsTaskManager} will insert additional parameters post user action.
*/
Class<? extends ExternalSystemTaskManager<PantsExecutionSettings>> taskManagerClass =
ExternalSystemManager.EP_NAME.findExtension(PantsManager.class).getTaskManagerClass();
assertEquals(PantsTaskManager.class, taskManagerClass);
String debuggerSetup = "dummy_debugger_setup";
GeneralCommandLine finalDebugCommandline = getFinalCommandline(esc, debuggerSetup, taskManagerClass);
List<String> expectedFinalDebugCommandlineParameters = Arrays.asList(
"--no-test-junit-timeouts",
"--jvm-test-junit-options=" + debuggerSetup,
"test",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:eight-test-platform",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:six",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:seven",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:eight",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:base",
"--test-junit-test=" + classReference
);
assertEquals(expectedFinalDebugCommandlineParameters, finalDebugCommandline.getParametersList().getParameters());
GeneralCommandLine finalRunCommandline = getFinalCommandline(esc, null, taskManagerClass);
List<String> expectedFinalRunCommandlineParameters = Arrays.asList(
"test",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:eight-test-platform",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:six",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:seven",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:eight",
"testprojects/tests/java/org/pantsbuild/testproject/testjvms:base",
"--test-junit-test=" + classReference
);
assertEquals(expectedFinalRunCommandlineParameters, finalRunCommandline.getParametersList().getParameters());
}
@NotNull
private GeneralCommandLine getFinalCommandline(
ExternalSystemRunConfiguration esc,
String debuggerSetup,
Class<? extends ExternalSystemTaskManager<PantsExecutionSettings>> taskManagerClass
) throws InstantiationException, IllegalAccessException {
GeneralCommandLine commandLine = ((PantsTaskManager) taskManagerClass.newInstance()).constructCommandLine(
esc.getSettings().getTaskNames(),
esc.getSettings().getExternalProjectPath(),
PantsExecutionSettings.createDefault(),
PantsUtil.parseCmdParameters(Optional.ofNullable(esc.getSettings().getVmOptions())),
PantsUtil.parseCmdParameters(Optional.ofNullable(esc.getSettings().getScriptParameters())),
debuggerSetup
);
assertNotNull(commandLine);
return commandLine;
}
public void testMethodRunConfiguration() throws Throwable {
doImport("testprojects/tests/java/org/pantsbuild/testproject/testjvms");
String classReference = "org.pantsbuild.testproject.testjvms.TestSix";
String methodName = "testSix";
PsiClass testClass = JavaPsiFacade.getInstance(myProject).findClass(classReference, GlobalSearchScope.allScope(myProject));
assertNotNull(testClass);
PsiMethod[] testMethods = testClass.findMethodsByName(methodName, false);
assertEquals(testMethods.length, 1);
PsiMethod testMethod = testMethods[0];
assertNotNull(testMethod);
ExternalSystemRunConfiguration esc = getExternalSystemRunConfiguration(testMethod);
Set<String> items = new HashSet<String>(Arrays.asList(esc.getSettings().getScriptParameters().split(" ")));
assertTrue(items.contains("--test-junit-test=" + classReference + "#" + methodName));
}
public void testModuleRunConfiguration() throws Throwable {
doImport("testprojects/tests/java/org/pantsbuild/testproject/testjvms");
PsiPackage testPackage = JavaPsiFacade.getInstance(myProject).findPackage("org.pantsbuild.testproject.testjvms");
assertEquals(1, testPackage.getDirectories().length);
ExternalSystemRunConfiguration esc = getExternalSystemRunConfiguration(testPackage.getDirectories()[0]);
Set<String> items = new HashSet<>(Arrays.asList(esc.getSettings().getScriptParameters().split(" ")));
assertTrue(items.contains("--test-junit-test=org.pantsbuild.testproject.testjvms.TestSix"));
assertTrue(items.contains("--test-junit-test=org.pantsbuild.testproject.testjvms.TestSeven"));
assertTrue(items.contains("--test-junit-test=org.pantsbuild.testproject.testjvms.TestEight"));
}
@NotNull
private ExternalSystemRunConfiguration getExternalSystemRunConfiguration(PsiElement psiElement) {
ConfigurationContext context = createContext(psiElement, new MapDataContext());
ConfigurationFromContext myPantsConfigurationFromContext = getPantsJunitConfigurationFromContext(context);
assertNotNull(myPantsConfigurationFromContext);
return (ExternalSystemRunConfiguration) myPantsConfigurationFromContext.getConfiguration();
}
private ConfigurationFromContext getPantsJunitConfigurationFromContext(ConfigurationContext context) {
for (RunConfigurationProducer producer : RunConfigurationProducer.getProducers(myProject)) {
if (producer instanceof PantsJUnitTestRunConfigurationProducer) {
return producer.createConfigurationFromContext(context);
}
}
return null;
}
private ConfigurationContext createContext(@NotNull PsiElement psiClass, @NotNull MapDataContext dataContext) {
dataContext.put(CommonDataKeys.PROJECT, myProject);
if (LangDataKeys.MODULE.getData(dataContext) == null) {
dataContext.put(LangDataKeys.MODULE, ModuleUtilCore.findModuleForPsiElement(psiClass));
}
dataContext.put(Location.DATA_KEY, PsiLocation.fromPsiElement(psiClass));
return ConfigurationContext.getFromContext(dataContext);
}
}