Move env tests to community.

This commit is contained in:
Dmitry Trofimov
2014-08-12 21:54:24 +02:00
39 changed files with 5495 additions and 0 deletions
@@ -0,0 +1,51 @@
package com.jetbrains.env;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.UsefulTestCase;
import java.util.List;
import java.util.Set;
/**
* @author traff
*/
public class PyEnvSufficiencyTest extends PyEnvTestCase {
private static final List<String> BASE_TAGS =
ImmutableList.<String>builder().add("python3", "django", "jython", "ipython", "ipython011", "ipython012", "nose", "pytest").build();
public void testSufficiency() {
if (UsefulTestCase.IS_UNDER_TEAMCITY && IS_ENV_CONFIGURATION) {
Set<String> tags = Sets.newHashSet();
List<String> roots = getPythonRoots();
if (roots.size() == 0) {
return; // not on env agent
}
for (String root : roots) {
tags.addAll(loadEnvTags(root));
}
List<String> missing = Lists.newArrayList();
for (String tag : necessaryTags()) {
if (!tags.contains(tag)) {
missing.add(tag);
}
}
assertEmpty("Agent is missing environments: " + StringUtil.join(missing, ", "), missing);
}
}
private static List<String> necessaryTags() {
if (SystemInfo.isWindows) {
return ImmutableList.<String>builder().addAll(BASE_TAGS).add("iron").build();
}
else {
return ImmutableList.<String>builder().addAll(BASE_TAGS).add("packaging").build();
}
}
}
+112
View File
@@ -0,0 +1,112 @@
package com.jetbrains.env;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
/**
* @author traff
*/
public class PyEnvTaskRunner {
private final List<String> myRoots;
public PyEnvTaskRunner(List<String> roots) {
myRoots = roots;
}
public void runTask(PyTestTask testTask, String testName) {
boolean wasExecuted = false;
List<String> passedRoots = Lists.newArrayList();
for (String root : myRoots) {
if (!isSuitableForTask(PyEnvTestCase.loadEnvTags(root), testTask) || !shouldRun(root, testTask)) {
continue;
}
try {
testTask.setUp(testName);
wasExecuted = true;
if (isJython(root)) {
testTask.useLongTimeout();
}
else {
testTask.useNormalTimeout();
}
final String executable = getExecutable(root, testTask);
if (executable == null) {
throw new RuntimeException("Cannot find Python interpreter in " + root);
}
testTask.runTestOn(executable);
passedRoots.add(root);
}
catch (Throwable e) {
throw new RuntimeException(
PyEnvTestCase.joinStrings(passedRoots, "Tests passed environments: ") + "Test failed on " + getEnvType() + " environment " + root,
e);
}
finally {
try {
testTask.tearDown();
}
catch (Exception e) {
throw new RuntimeException("Couldn't tear down task", e);
}
}
}
if (!wasExecuted) {
throw new RuntimeException("test" +
testName +
" was not executed.\n" +
PyEnvTestCase.joinStrings(myRoots, "All roots: ") +
"\n" +
PyEnvTestCase.joinStrings(testTask.getTags(), "Required tags in tags.txt in root: "));
}
}
protected boolean shouldRun(String root, PyTestTask task) {
return true;
}
protected String getExecutable(String root, PyTestTask testTask) {
return PythonSdkType.getPythonExecutable(root);
}
protected String getEnvType() {
return "local";
}
private static boolean isSuitableForTask(List<String> tags, PyTestTask task) {
return isSuitableForTags(tags, task.getTags());
}
public static boolean isSuitableForTags(List<String> envTags, Set<String> taskTags) {
Set<String> necessaryTags = Sets.newHashSet(taskTags);
for (String tag : envTags) {
necessaryTags.remove(tag.trim());
}
for (String tag : taskTags) {
if (tag.startsWith("-")) { //do not run on envs with that tag
if (envTags.contains(tag.substring(1))) {
return false;
}
necessaryTags.remove(tag);
}
}
return necessaryTags.isEmpty();
}
protected static boolean isJython(@NotNull String sdkHome) {
return sdkHome.toLowerCase().contains("jython");
}
}
+201
View File
@@ -0,0 +1,201 @@
package com.jetbrains.env;
import com.google.common.collect.Lists;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.util.SystemProperties;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.fixtures.PyTestCase;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assume;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/**
* @author traff
*/
public abstract class PyEnvTestCase extends UsefulTestCase {
private static final Logger LOG = Logger.getInstance(PyEnvTestCase.class.getName());
private static final String TAGS_FILE = "tags.txt";
private static final String PYCHARM_PYTHON_ENVS = "PYCHARM_PYTHON_ENVS";
private static final String PYCHARM_PYTHON_VIRTUAL_ENVS = "PYCHARM_PYTHON_VIRTUAL_ENVS";
protected static final boolean IS_ENV_CONFIGURATION = System.getProperty("pycharm.env") != null;
public static final boolean RUN_REMOTE = SystemProperties.getBooleanProperty("pycharm.run_remote", false);
public static final boolean RUN_LOCAL = SystemProperties.getBooleanProperty("pycharm.run_local", true);
/**
* Tags that should exist between all tags, available on all interpreters for test to run.
* See {@link #PyEnvTestCase(String...)}
*/
@Nullable
private final String[] myRequiredTags;
/**
* @param requiredTags tags that should exist on some interpreter for this test to run.
* if some of these tags do not exist on any interpreter, all test methods would be skipped using
* {@link org.junit.Assume}.
* See <a href="http://junit.sourceforge.net/javadoc/org/junit/Assume.html">Assume manual</a>.
* Check [IDEA-122939] and [TW-25043] as well.
*/
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
protected PyEnvTestCase(@NotNull final String... requiredTags) {
myRequiredTags = requiredTags.length > 0 ? requiredTags.clone() : null;
PyTestCase.initPlatformPrefix();
}
@Override
public void setUp() throws Exception {
super.setUp();
if (myRequiredTags != null) { // Ensure all tags exist between available interpreters
Assume.assumeThat(
"Can't find some tags between all available interpreter, test (all methods) will be skipped",
getAvailableTags(),
Matchers.hasItems(myRequiredTags)
);
}
}
/**
* @return all tags available between all interpreters
*/
@NotNull
private static Collection<String> getAvailableTags() {
final Collection<String> allAvailableTags = new HashSet<String>();
for (final String pythonRoot : getPythonRoots()) {
allAvailableTags.addAll(loadEnvTags(pythonRoot));
}
return allAvailableTags;
}
@Override
protected void invokeTestRunnable(@NotNull final Runnable runnable) throws Exception {
if (runInWriteAction()) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(runnable);
}
});
}
else {
runnable.run();
}
}
@Override
protected boolean runInDispatchThread() {
return false;
}
protected boolean runInWriteAction() {
return false;
}
public void runPythonTest(final PyTestTask testTask) {
runTest(testTask, getTestName(false));
}
public void runTest(@NotNull PyTestTask testTask, @NotNull String testName) {
if (notEnvConfiguration()) {
fail("Running under teamcity but not by Env configuration. Skipping.");
return;
}
List<String> roots = getPythonRoots();
if (roots.size() == 0) {
String msg = testName +
": environments are not defined. Skipping. \nSpecify either " +
PYCHARM_PYTHON_ENVS +
" or " +
PYCHARM_PYTHON_VIRTUAL_ENVS +
" environment variable.";
LOG.warn(msg);
System.out.println(msg);
return;
}
doRunTests(testTask, testName, roots);
}
protected void doRunTests(PyTestTask testTask, String testName, List<String> roots) {
if (RUN_LOCAL) {
PyEnvTaskRunner taskRunner = new PyEnvTaskRunner(roots);
taskRunner.runTask(testTask, testName);
}
}
public static boolean notEnvConfiguration() {
return UsefulTestCase.IS_UNDER_TEAMCITY && !IS_ENV_CONFIGURATION;
}
public static List<String> getPythonRoots() {
List<String> roots = Lists.newArrayList();
String envs = System.getenv(PYCHARM_PYTHON_ENVS);
if (envs != null) {
roots.addAll(Lists.newArrayList(envs.split(File.pathSeparator)));
}
String virtualEnvs = System.getenv(PYCHARM_PYTHON_VIRTUAL_ENVS);
if (virtualEnvs != null) {
roots.addAll(readVirtualEnvRoots(virtualEnvs));
}
return roots;
}
protected static List<String> readVirtualEnvRoots(@NotNull String envs) {
List<String> result = Lists.newArrayList();
String[] roots = envs.split(File.pathSeparator);
for (String root : roots) {
File virtualEnvRoot = new File(root);
File[] virtualenvs = virtualEnvRoot.listFiles();
if (virtualenvs != null) {
for (File f : virtualenvs) {
result.add(f.getAbsolutePath());
}
} else {
LOG.error(root + " is not a directory of doesn't exist");
}
}
return result;
}
public static List<String> loadEnvTags(String env) {
List<String> envTags;
try {
File parent = new File(env);
if (parent.isFile()) {
parent = parent.getParentFile();
}
envTags = com.intellij.openapi.util.io.FileUtil.loadLines(new File(parent, TAGS_FILE));
}
catch (IOException e) {
envTags = Lists.newArrayList();
}
return envTags;
}
public static String joinStrings(Collection<String> roots, String rootsName) {
return roots.size() > 0 ? rootsName + StringUtil.join(roots, ", ") + "\n" : "";
}
}
@@ -0,0 +1,174 @@
package com.jetbrains.env;
import com.google.common.collect.Lists;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.ide.util.projectWizard.EmptyModuleBuilder;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleTypeManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.builders.ModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.*;
import com.intellij.testFramework.fixtures.impl.ModuleFixtureBuilderImpl;
import com.intellij.testFramework.fixtures.impl.ModuleFixtureImpl;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.PythonModuleTypeBase;
import com.jetbrains.python.fixtures.PyProfessionalTestCase;
import com.jetbrains.python.sdk.InvalidSdkException;
import com.jetbrains.python.sdkTools.PyTestSdkTools;
import com.jetbrains.python.sdkTools.SdkCreationType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
* @author traff
*/
public abstract class PyExecutionFixtureTestTask extends PyTestTask {
public static final int NORMAL_TIMEOUT = 30000;
public static final int LONG_TIMEOUT = 120000;
protected int myTimeout = NORMAL_TIMEOUT;
protected CodeInsightTestFixture myFixture;
public Project getProject() {
return myFixture.getProject();
}
public void useNormalTimeout() {
myTimeout = NORMAL_TIMEOUT;
}
public void useLongTimeout() {
myTimeout = LONG_TIMEOUT;
}
public void setUp(final String testName) throws Exception {
initFixtureBuilder();
final TestFixtureBuilder<IdeaProjectTestFixture> fixtureBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(
testName);
myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(fixtureBuilder.getFixture());
UIUtil.invokeAndWaitIfNeeded(
new Runnable() {
@Override
public void run() {
ModuleFixtureBuilder moduleFixtureBuilder = fixtureBuilder.addModule(MyModuleFixtureBuilder.class);
moduleFixtureBuilder.addSourceContentRoot(myFixture.getTempDirPath());
moduleFixtureBuilder.addSourceContentRoot(getTestDataPath());
final List<String> contentRoots = getContentRoots();
for (String contentRoot : contentRoots) {
moduleFixtureBuilder.addContentRoot(getTestDataPath() + contentRoot);
}
}
}
);
myFixture.setUp();
myFixture.setTestDataPath(getTestDataPath());
}
protected List<String> getContentRoots() {
return Lists.newArrayList();
}
protected String getTestDataPath() {
return PyProfessionalTestCase.getProfessionalTestDataPath();
}
protected void initFixtureBuilder() {
IdeaTestFixtureFactory.getFixtureFactory().registerFixtureBuilder(MyModuleFixtureBuilder.class, MyModuleFixtureBuilderImpl.class);
}
public void tearDown() throws Exception {
if (myFixture != null) {
myFixture.tearDown();
myFixture = null;
}
}
@Nullable
protected LightProjectDescriptor getProjectDescriptor() {
return null;
}
protected void disposeProcess(ProcessHandler h) throws InterruptedException {
h.destroyProcess();
if (!waitFor(h)) {
new Throwable("Can't stop process").printStackTrace();
}
}
protected boolean waitFor(ProcessHandler p) throws InterruptedException {
return p.waitFor(myTimeout);
}
protected boolean waitFor(@NotNull Semaphore s) throws InterruptedException {
return waitFor(s, myTimeout);
}
protected static boolean waitFor(@NotNull Semaphore s, long timeout) throws InterruptedException {
return s.tryAcquire(timeout, TimeUnit.MILLISECONDS);
}
public static class MyModuleFixtureBuilderImpl extends ModuleFixtureBuilderImpl<ModuleFixture> implements MyModuleFixtureBuilder {
public MyModuleFixtureBuilderImpl(TestFixtureBuilder<? extends IdeaProjectTestFixture> fixtureBuilder) {
super(new PlatformPythonModuleType(), fixtureBuilder);
}
@Override
protected ModuleFixture instantiateFixture() {
return new ModuleFixtureImpl(this);
}
}
public static class PlatformPythonModuleType extends PythonModuleTypeBase<EmptyModuleBuilder> {
@NotNull
public static PlatformPythonModuleType getInstance() {
return (PlatformPythonModuleType)ModuleTypeManager.getInstance().findByID(PYTHON_MODULE);
}
@NotNull
@Override
public EmptyModuleBuilder createModuleBuilder() {
return new EmptyModuleBuilder() {
@Override
public ModuleType getModuleType() {
return getInstance();
}
};
}
}
/**
* Creates SDK by its path
*
* @param sdkHome path to sdk (probably obtained by {@link #runTestOn(String)})
* @param sdkCreationType SDK creation strategy (see {@link com.jetbrains.python.sdkTools.SdkCreationType} doc)
* @return sdk
*/
@NotNull
protected Sdk createTempSdk(@NotNull final String sdkHome, @NotNull final SdkCreationType sdkCreationType)
throws InvalidSdkException, IOException {
final VirtualFile sdkHomeFile = LocalFileSystem.getInstance().findFileByPath(sdkHome);
Assert.assertNotNull("Interpreter file not found: " + sdkHome, sdkHomeFile);
return PyTestSdkTools.createTempSdk(sdkHomeFile, sdkCreationType, myFixture.getModule());
}
public interface MyModuleFixtureBuilder extends ModuleFixtureBuilder<ModuleFixture> {
}
}
+81
View File
@@ -0,0 +1,81 @@
package com.jetbrains.env;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.io.FileUtil;
import java.util.Set;
/**
* @author traff
*/
public abstract class PyTestTask {
private String myWorkingFolder;
private String myScriptName;
private String myScriptParameters;
public void setWorkingFolder(String workingFolder) {
myWorkingFolder = workingFolder;
}
public void setScriptName(String scriptName) {
myScriptName = scriptName;
}
public void setScriptParameters(String scriptParameters) {
myScriptParameters = scriptParameters;
}
public void setUp(String testName) throws Exception {
}
public void tearDown() throws Exception {
}
/**
* Run test on certain SDK path.
* To create SDK from path, use {@link PyExecutionFixtureTestTask#createTempSdk(String, com.jetbrains.python.sdkTools.SdkCreationType)}
*
* @param sdkHome sdk path
*/
public abstract void runTestOn(String sdkHome) throws Exception;
public void before() throws Exception {
}
public void testing() throws Exception {
}
public void after() throws Exception {
}
public void useNormalTimeout() {
}
public void useLongTimeout() {
}
public String getScriptName() {
return myScriptName;
}
public String getScriptPath() {
return getFilePath(myScriptName);
}
public String getFilePath(String scriptName) {
return FileUtil
.toSystemDependentName(myWorkingFolder.endsWith("/") ? myWorkingFolder + scriptName : myWorkingFolder + "/" + scriptName);
}
public String getScriptParameters() {
return myScriptParameters;
}
public String getWorkingFolder() {
return myWorkingFolder;
}
public Set<String> getTags() {
return Sets.newHashSet();
}
}
@@ -0,0 +1,148 @@
package com.jetbrains.env.django;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.django.facet.DjangoFacet;
import com.jetbrains.django.fixtures.DjangoTestCase;
import com.jetbrains.env.python.debug.PyDebuggerTask;
import com.jetbrains.python.fixtures.PyProfessionalTestCase;
import com.jetbrains.python.templateLanguages.TemplatesService;
import org.junit.Assert;
import java.net.URL;
import java.net.URLConnection;
import java.util.Scanner;
import java.util.Set;
/**
* @author traff
*/
public class DjangoEnvTestTask extends PyDebuggerTask {
protected final int myPort;
protected String getTestDataPath() {
return PyProfessionalTestCase.getProfessionalTestDataPath() + "/django/debug";
}
public DjangoEnvTestTask(String workingFolder, String scriptName, String scriptParameters, int port) {
setWorkingFolder(getTestDataPath() + workingFolder);
setScriptName(scriptName);
setScriptParameters(scriptParameters + port);
myPort = port;
}
@Override
public void setUp(String testName) throws Exception {
super.setUp(testName);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
Module module = myFixture.getModule();
if (module != null && !DjangoFacet.isPresent(module)) {
DjangoTestCase.addDjangoFacet(module);
TemplatesService.getInstance(module).setTemplateLanguage(TemplatesService.DJANGO);
}
TemplatesService.getInstance(module).setTemplateLanguage(TemplatesService.DJANGO);
}
});
}
@Override
public void tearDown() throws Exception {
TemplatesService.getInstance(myFixture.getModule()).setTemplateLanguage(TemplatesService.NONE);
super.tearDown();
}
public static void checkModuleForFile(Project project, VirtualFile vFile) {
Module module = ModuleUtil.findModuleForFile(vFile, project);
Assert.assertNotNull(module); //should be in our module for correct breakpoints setting
Assert.assertTrue(DjangoFacet.isPresent(module));
}
static class Response {
private final String content;
public Response(String content) {
this.content = content;
}
public void contains(String string) {
Assert.assertTrue("Cant find '" + string + "' in content: \n" + content, content.contains(string));
}
public static Response load(String address) {
StringBuilder sb = new StringBuilder();
try {
Thread.sleep(500);
// Send data
URL url = new URL(address);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setConnectTimeout(0);
conn.setReadTimeout(0);
conn.setUseCaches(false);
// Get the response
Scanner s = new Scanner(conn.getInputStream());
while (s.hasNextLine()) {
String line = s.nextLine();
sb.append(line + "\n");
// Process line...
}
}
catch (Exception e) {
sb = new StringBuilder(e.getMessage());
}
return new Response(sb.toString());
}
}
protected static LoadingPage loadPage(final String url) {
final Ref<DjangoEnvTestTask.Response> response = Ref.create(null);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
response.set(Response.load("http://127.0.0.1:" + url));
}
});
thread.start();
return new LoadingPage(thread, response);
}
protected static class LoadingPage {
private Thread myThread;
private Ref<Response> myResponse;
public LoadingPage(Thread thread, Ref<Response> response) {
myThread = thread;
myResponse = response;
}
public void join() throws InterruptedException {
myThread.join();
}
public Response get() throws InterruptedException {
join();
return myResponse.get();
}
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("django");
}
protected void waitForStart() throws InterruptedException {
waitForOutput("Development server is running", "Starting development server");
}
}
@@ -0,0 +1,68 @@
package com.jetbrains.env.django;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.jetbrains.django.actions.manage.ManageTaskActions;
import com.jetbrains.django.manage.BaseCommand;
import com.jetbrains.django.testRunner.DjangoTestsConfigurationType;
import com.jetbrains.django.util.DjangoUtil;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
/**
* @author Ilya.Kazakevich
*/
public class DjangoManageTaskActionsTest extends PyEnvTestCase {
/**
* Checks that "manage.py" UI displays correct commands
*/
public void testManageCommands() throws Exception {
runPythonTest(new DjangoManageCommandsTestTask());
}
private static class DjangoManageCommandsTestTask extends DjangoPathTestTask {
@Nullable
@Override
public ConfigurationFactory getFactory() {
return DjangoTestsConfigurationType.getInstance().getConfigurationFactories()[0];
}
@Override
protected void configure(final AbstractPythonRunConfiguration config) throws IOException {
super.configure(config);
final Module module = config.getModule();
assert module != null : "Config has no module";
ModuleRootModificationUtil.setModuleSdk(module, config.getSdk());
Assert.assertNotNull("Django not found", DjangoUtil.getDjangoPath(config.getSdk()));
final Collection<String> expectedCommands = new HashSet<String>();
expectedCommands.add("runserver");
expectedCommands.add("dbshell");
expectedCommands.add("syncdb");
if (DjangoUtil.isDjangoVersionAtLeast(myFixture.getModule(), 7)) {
expectedCommands.add("makemigrations");
expectedCommands.add("migrate");
}
final List<BaseCommand> commands = ManageTaskActions.getInstance().getCommands(myFixture.getModule());
for (final BaseCommand command : commands) {
expectedCommands.remove(command.getCommand());
}
Assert.assertTrue(String.format("Commands '%s' were not found between %s", expectedCommands, commands), expectedCommands.isEmpty());
}
}
}
@@ -0,0 +1,276 @@
package com.jetbrains.env.django;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.XDebuggerTestUtil;
import com.jetbrains.django.facet.DjangoFacet;
import com.jetbrains.django.fixtures.DjangoTestCase;
import com.jetbrains.django.manage.DjangoManageTask;
import com.jetbrains.django.testRunner.DjangoTestsConfigurationType;
import com.jetbrains.django.ui.DjangoBundle;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import com.jetbrains.python.run.PythonTracebackFilter;
import com.jetbrains.python.sdk.InvalidSdkException;
import com.jetbrains.python.sdkTools.SdkCreationType;
import com.jetbrains.python.templateLanguages.TemplatesService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import java.io.IOException;
import java.util.Set;
/**
* @author traff
*/
public abstract class DjangoManageTestTask extends PyExecutionFixtureTestTask {
private StringBuilder myOutput;
private StringBuilder myStdErr;
private StringBuilder myStdOut;
private RunContentDescriptor myDescriptor;
private ProcessHandler myProcessHandler;
private ExecutionConsole myConsoleView;
private Sdk mySdk;
private RunContentExecutor myRunContentExecutor;
@Override
protected abstract String getTestDataPath();
@Override
public void setUp(String testName) throws Exception {
super.setUp(testName);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
Module module = myFixture.getModule();
if (module != null && !DjangoFacet.isPresent(module)) {
DjangoTestCase.addDjangoFacet(module);
TemplatesService.getInstance(module).setTemplateLanguage(TemplatesService.DJANGO);
}
TemplatesService.getInstance(module).setTemplateLanguage(TemplatesService.DJANGO);
}
});
}
@Override
public void tearDown() throws Exception {
TemplatesService.getInstance(myFixture.getModule()).setTemplateLanguage(TemplatesService.NONE);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
try {
if (myConsoleView != null) {
Disposer.dispose(myConsoleView);
myConsoleView = null;
}
if (myDescriptor != null) {
Disposer.dispose(myDescriptor);
myDescriptor = null;
}
if (myRunContentExecutor != null) {
Disposer.dispose(myRunContentExecutor);
}
DjangoManageTestTask.super.tearDown();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
@Nullable
public abstract ConfigurationFactory getFactory();
@Override
public void runTestOn(final String sdkHome) throws Exception {
mySdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_ONLY);
before();
final Semaphore s = new Semaphore();
s.down();
myOutput = new StringBuilder();
myStdErr = new StringBuilder();
myStdOut = new StringBuilder();
runProcess(sdkHome, s);
try {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
try {
testing();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
Assert.assertTrue(s.waitFor(60000));
XDebuggerTestUtil.waitForSwing();
after();
}
finally {
disposeProcess(myProcessHandler);
}
}
private void runProcess(final String sdkHome, final Semaphore s) throws ExecutionException, IOException, InvalidSdkException {
final ConfigurationFactory factory = getFactory();
if (factory == null) { // PythonTask (there is no run configuration)
final Module module = myFixture.getModule();
final DjangoManageTask task = new DjangoManageTask(module, DjangoBundle.message("manage.run.tab.name"), mySdk);
task.setWorkingDirectory(getWorkingFolder());
task.setRunnerScript(PythonHelpersLocator.getHelperPath("pycharm/django_manage.py"));
ImmutableList.Builder<String> parametersString =
new ImmutableList.Builder<String>().add(getSubcommand()).add(getTestDataPath());
task.setParameters(parametersString.build());
myProcessHandler = task.createProcess(null);
myProcessHandler.addProcessListener(createProcessListener());
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
final Project project = myFixture.getProject();
myRunContentExecutor = new RunContentExecutor(project, myProcessHandler);
myRunContentExecutor
.withFilter(new PythonTracebackFilter(project))
.run();
}
});
s.up();
}
else { //run dango server and django test
final Project project = getProject();
final RunnerAndConfigurationSettings settings =
RunManager.getInstance(project).createRunConfiguration("test", factory);
final AbstractPythonRunConfiguration config = (AbstractPythonRunConfiguration)settings.getConfiguration();
config.addSourceRoots(DjangoTestsConfigurationType.getInstance().getDjangoTestsFactory().equals(factory));
config.addContentRoots(DjangoTestsConfigurationType.getInstance().getDjangoTestsFactory().equals(factory));
config.setSdkHome(sdkHome);
config.setWorkingDirectory(getWorkingFolder());
new WriteAction() {
@Override
protected void run(Result result) throws Throwable {
configure(config);
RunManagerEx.getInstanceEx(project).addConfiguration(settings, false);
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(settings);
Assert.assertSame(settings, RunManagerEx.getInstanceEx(project).getSelectedConfiguration());
}
}.execute();
final ProgramRunner runner = ProgramRunnerUtil.getRunner(DefaultRunExecutor.EXECUTOR_ID, settings);
Assert.assertTrue(runner.canRun(DefaultRunExecutor.EXECUTOR_ID, config));
final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
final ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, settings, project);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
try {
runner.execute(env, new ProgramRunner.Callback() {
@Override
public void processStarted(RunContentDescriptor descriptor) {
myDescriptor = descriptor;
myProcessHandler = myDescriptor.getProcessHandler();
myProcessHandler.addProcessListener(createProcessListener());
myConsoleView = myDescriptor.getExecutionConsole();
s.up();
}
});
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
}
private ProcessAdapter createProcessListener() {
return new ProcessAdapter() {
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
myOutput.append(event.getText());
if (outputType == ProcessOutputTypes.STDOUT) {
myStdOut.append(event.getText());
}
else if (outputType == ProcessOutputTypes.STDERR) {
myStdErr.append(event.getText());
}
}
};
}
protected abstract String getSubcommand();
protected void configure(AbstractPythonRunConfiguration config) throws IOException {
}
@NotNull
protected String output() {
return myOutput.toString();
}
@NotNull
protected String stderr() {
return myStdErr.toString();
}
@NotNull
protected String stdout() {
return myStdOut.toString();
}
public void waitForOutput(@NotNull final String string) throws InterruptedException {
int count = 0;
while (!output().contains(string)) {
if (count > 10) {
Assert.fail("'" + string + "'" + " is not present in output.\n" + output());
}
Thread.sleep(2000);
count++;
}
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("django");
}
}
@@ -0,0 +1,100 @@
package com.jetbrains.env.django;
import com.google.common.collect.Lists;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.util.io.FileUtil;
import com.jetbrains.django.run.DjangoServerRunConfiguration;
import com.jetbrains.django.run.DjangoServerRunConfigurationType;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import junit.framework.Assert;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.ArrayList;
/**
* User : catherine
*/
public class DjangoPathTest extends PyEnvTestCase {
/**
* This string is printed after printing sys.path in djangoPath/settings.py
*/
public static final String THE_END_OF_SYS_PATH = "The end of sys.path";
public void testRunserverPath() throws IOException {
runPythonTest(new DjangoPathTestTask() {
@Override
protected void configure(AbstractPythonRunConfiguration config) throws IOException {
final int[] ports = DjangoTemplateDebuggerTest.findFreePorts(2);
((DjangoServerRunConfiguration)config).setPort(ports[1]);
((DjangoServerRunConfiguration)config).setRunNoReload(true);
}
@Override
public ConfigurationFactory getFactory() {
return DjangoServerRunConfigurationType.getInstance().getConfigurationFactories()[0];
}
public void testing() throws Exception {
waitForOutput(THE_END_OF_SYS_PATH);
doTest(output(), getTestDataPath());
}
});
}
private static void doTest(String output, String testDataPath) {
final String[] splittedOutput = output.split("\\n");
final ArrayList<String> outputList = Lists.newArrayList();
for (String s : splittedOutput) {
if (s.equals(THE_END_OF_SYS_PATH)) {
break;
}
outputList.add(norm(s));
}
testDataPath = norm(testDataPath);
Assert.assertEquals(testDataPath, outputList.get(1));
assertEquals(outputList.indexOf(testDataPath),
outputList.lastIndexOf(testDataPath));
}
private static String norm(String testDataPath) {
return FileUtil.toSystemIndependentName(testDataPath);
}
public void testManagePath() throws IOException {
runPythonTest(new DjangoPathTestTask() {
@Nullable
@Override
public ConfigurationFactory getFactory() {
return null;
}
public void testing() throws Exception {
waitForOutput(THE_END_OF_SYS_PATH);
final String[] splittedOutput = output().split("\\n");
final ArrayList<String> outputList = Lists.newArrayList();
for (String s : splittedOutput) {
if (s.equals(THE_END_OF_SYS_PATH)) {
break;
}
outputList.add(s);
}
assertEquals(getTestDataPath(), outputList.get(1));
assertEquals(outputList.indexOf(getTestDataPath()),
outputList.lastIndexOf(getTestDataPath()));
}
});
}
}
@@ -0,0 +1,19 @@
package com.jetbrains.env.django;
import com.jetbrains.python.fixtures.PyProfessionalTestCase;
/**
* User : catherine
*/
public abstract class DjangoPathTestTask extends DjangoManageTestTask {
@Override
protected String getTestDataPath() {
return PyProfessionalTestCase.getProfessionalTestDataPath() + "/django/path/djangoPath";
}
@Override
protected String getSubcommand() {
return "validate";
}
}
@@ -0,0 +1,144 @@
package com.jetbrains.env.django;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;
import com.intellij.execution.ExecutionException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.UsefulTestCase;
import com.jetbrains.django.DjangoNames;
import com.jetbrains.django.model.DjangoAdmin;
import com.jetbrains.django.util.DjangoUtil;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.blockEvaluator.PyBlockEvaluator;
import com.jetbrains.python.sdkTools.SdkCreationType;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* Tests projection creation for Django
*
* @author Ilya.Kazakevich
*/
public class DjangoProjectCreationTest extends PyEnvTestCase {
private static final String ROOT_FOLDER_NAME = "content_root";
private static final String WEB_SITE_NAME = "myWebSite";
private static final String DJANGO_TAG = "django";
private static final MyDjangoProjectCreationTest.Canonicator CANONICATOR = new MyDjangoProjectCreationTest.Canonicator();
public DjangoProjectCreationTest() {
super(DJANGO_TAG);
}
// TODO: Doc
public void testProjectWithTemplates() throws Exception {
runPythonTest(new MyDjangoProjectCreationTest());
}
private static class MyDjangoProjectCreationTest extends PyExecutionFixtureTestTask {
@Override
public void runTestOn(@NotNull final String sdkHome) throws Exception {
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_ONLY);
final String djangoPath = DjangoUtil.getDjangoPath(sdk);
assert djangoPath != null : "No django found under " + sdkHome;
final VirtualFile contentRoot = myFixture.getTempDirFixture().findOrCreateDir(ROOT_FOLDER_NAME);
final String templateDir = myFixture.getTempDirFixture().findOrCreateDir(ROOT_FOLDER_NAME + "/templates_dir").getCanonicalPath();
assert templateDir != null : "Failed to create template dirs";
UsefulTestCase.edt(new Runnable() {
@Override
public void run() {
new WriteAction() {
@Override
protected void run(@NotNull Result result) throws Throwable {
try {
DjangoAdmin.createProject(
myFixture.getProject(),
sdk,
contentRoot,
WEB_SITE_NAME,
"myMainApp",
templateDir,
djangoPath,
false,
false
);
}
catch (final ExecutionException ex) {
Assert.fail(ex.toString());
}
}
}.execute();
}
});
final String pathToSettingsPy;
if (DjangoAdmin.isDjangoVersionAtLeast(sdk, "1.4")) {
pathToSettingsPy = ROOT_FOLDER_NAME + '/' + WEB_SITE_NAME + '/' + DjangoNames.SETTINGS_FILE;
}
else {
pathToSettingsPy = ROOT_FOLDER_NAME + '/' + DjangoNames.SETTINGS_FILE;
}
final PyFile settingsPy =
PyUtil.as(myFixture.configureByFile(pathToSettingsPy), PyFile.class);
Assert.assertNotNull(DjangoNames.SETTINGS_FILE + " not created", settingsPy);
Assert.assertEquals("Bad file name for settings", DjangoNames.SETTINGS_FILE, settingsPy.getName());
final PyBlockEvaluator evaluator = new PyBlockEvaluator();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
evaluator.evaluate(settingsPy);
}
});
final List<String> templateDirsFromConfig = evaluator.getValueAsStringList(DjangoNames.TEMPLATE_DIRS_SETTING);
Assert.assertThat(String.format("Failed to find %s in %s", DjangoNames.TEMPLATE_DIRS_SETTING, settingsPy), templateDirsFromConfig,
Matchers.allOf(Matchers.notNullValue(), Matchers.not(Matchers.empty())));
// Canoncial path is used to prevent ".."
Assert.assertThat("Wrong template dirs in config", Collections2.transform(templateDirsFromConfig, CANONICATOR),
Matchers.contains(CANONICATOR.apply(templateDir)));
}
@Override
public Set<String> getTags() {
return Sets.newHashSet(DJANGO_TAG);
}
// Makes canoncial path from any path
private static class Canonicator implements Function<String, String> {
@Override
public String apply(final String input) {
try {
return new File(input).getCanonicalPath();
}
catch (final IOException e) {
throw new AssertionError("Errror with file " + input + " : " + e);
}
}
}
}
}
@@ -0,0 +1,63 @@
package com.jetbrains.env.django;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
import com.intellij.xdebugger.XDebuggerUtil;
import com.jetbrains.django.fixtures.DjangoTestCase;
import junit.framework.Assert;
/**
* @author traff
*/
public class DjangoTemplateBreakpointsTest extends DjangoTestCase {
@Override
protected String getTestDataPath() {
return super.getTestDataPath() + "/django/debug/";
}
public void testCanSetBreakpoints() {
prepareProject("djangoDebug");
inFile("djangoDebug/templates/test1.html")
.notCan(0)
.notCan(1)
.notCan(2)
.can(3)
.notCan(4)
.can(5)
.can(6)
.notCan(7)
.can(8)
.can(9)
.notCan(10)
.notCan(11)
.notCan(12);
}
private OpenedTemplate inFile(String fileName) {
return new OpenedTemplate(fileName, myFixture);
}
private static class OpenedTemplate {
private String myFile;
private CodeInsightTestFixture myFixture;
private OpenedTemplate(String file, CodeInsightTestFixture fixture) {
myFile = file;
myFixture = fixture;
}
private OpenedTemplate can(int line) {
Assert.assertTrue("at line " + line, XDebuggerUtil.getInstance().canPutBreakpointAt(myFixture.getProject(), findFile(), line));
return this;
}
private VirtualFile findFile() {
return myFixture.findFileInTempDir(myFile);
}
private OpenedTemplate notCan(int line) {
Assert.assertFalse("at line " + line, XDebuggerUtil.getInstance().canPutBreakpointAt(myFixture.getProject(), findFile(), line));
return this;
}
}
}
@@ -0,0 +1,361 @@
package com.jetbrains.env.django;
import com.google.common.collect.Sets;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.xdebugger.XDebuggerTestUtil;
import com.jetbrains.django.util.VirtualFileUtil;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.python.debugger.django.DjangoExceptionBreakpointProperties;
import com.jetbrains.python.debugger.django.DjangoExceptionBreakpointType;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Set;
/**
* @author traff
*/
public class DjangoTemplateDebuggerTest extends PyEnvTestCase {
public void testBreakpointStopAndEval() throws IOException {
final int[] ports = findFreePorts(2);
runPythonTest(new BreakpointStopAndEvalTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]));
}
private static class BreakpointStopAndEvalTask extends DjangoEnvTestTask {
public BreakpointStopAndEvalTask(String workingFolder, String scriptName, String scriptParameters, int port) {
super(workingFolder, scriptName, scriptParameters, port);
}
@Override
public void before() throws Exception {
//setShouldPrintOutput(true);
String file = getFilePath("/templates/test1.html");
checkModuleForFile(getProject(), VirtualFileUtil.findFile(file));
toggleBreakpoint(file, 6);
}
@Override
public void testing() throws Exception {
waitForStart();
DjangoEnvTestTask.LoadingPage page = loadPage(myPort + "/test1");
waitForPause();
eval("x").hasValue("1");
resume();
waitForPause();
eval("x").hasValue("2");
resume();
waitForPause();
eval("x").hasValue("3");
resume();
page.get().contains("TemplateDebugging");
}
}
/* TODO: uncomment after fixing http://youtrack.jetbrains.com/issue/PY-13465
public void testSetVal() throws IOException {
//setShouldPrintOutput(true);
final int[] ports = findFreePorts(2);
runPythonTest(new DjangoEnvTestTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]) {
@Override
public void before() throws Exception {
String file = getFilePath("/templates/test1.html");
checkModuleForFile(getProject(), VirtualFileUtil.findFile(file));
toggleBreakpoint(file, 6);
}
@Override
public void testing() throws Exception {
waitForStart();
LoadingPage page = loadPage(myPort + "/test1");
waitForPause();
eval("x").hasValue("1");
eval("name").hasValue("'TemplateDebugging'");
setVal("name", "'TemplateDjangoDebugging'");
resume();
waitForPause();
eval("x").hasValue("2");
eval("name").hasValue("'TemplateDjangoDebugging'");
resume();
waitForPause();
eval("x").hasValue("3");
eval("name").hasValue("'TemplateDjangoDebugging'");
resume();
page.get().contains("templatedjangodebugging");
}
});
}
*/
public void testVariableDoesNotExistExceptionBreak() throws IOException {
//setShouldPrintOutput(true);
final int[] ports = findFreePorts(2);
runPythonTest(new DjangoEnvTestTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]) {
@Override
public void before() throws Exception {
addDjangoExceptionBreakpoint(myFixture);
}
@Override
public void testing() throws Exception {
waitForStart();
LoadingPage page = loadPage(myPort + "/test2");
waitForPause();
eval("x").hasValue("1");
resume();
waitForPause();
eval("x").hasValue("2");
resume();
waitForPause();
eval("x").hasValue("3");
resume();
page.get().contains("templatedebugging");
}
});
}
public void testTemplateDoseNotExistsExceptionBreak() throws IOException {
//setShouldPrintOutput(true);
final int[] ports = findFreePorts(2);
runPythonTest(new DjangoEnvTestTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]) {
@Override
public void before() throws Exception {
addDjangoExceptionBreakpoint(myFixture);
}
@Override
public void testing() throws Exception {
waitForStart();
LoadingPage page = loadPage(myPort + "/test3");
waitForPause();
resume();
page.get().contains("Server returned HTTP response code: 500");
}
});
}
public void testConditionalBreakpointStop() throws IOException {
final int[] ports = findFreePorts(2);
runPythonTest(new DjangoEnvTestTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]) {
@Override
public void before() throws Exception {
//setShouldPrintOutput(true);
String file = getFilePath("/templates/test1.html");
checkModuleForFile(getProject(), VirtualFileUtil.findFile(file));
toggleBreakpoint(file, 6);
XDebuggerTestUtil.setBreakpointCondition(getProject(), 6, "x == 1 or x == 3");
}
@Override
public void testing() throws Exception {
waitForStart();
LoadingPage page = loadPage(myPort + "/test1");
waitForPause();
eval("x").hasValue("1");
resume();
waitForPause();
eval("x").hasValue("3");
resume();
page.get().contains("TemplateDebugging");
}
});
}
public void testBreakpointStopAndStepOver() throws IOException {
final int[] ports = findFreePorts(2);
runPythonTest(new DjangoEnvTestTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]) {
@Override
public void before() throws Exception {
//setShouldPrintOutput(true);
String file = getFilePath("/templates/test4.html");
checkModuleForFile(getProject(), VirtualFileUtil.findFile(file));
toggleBreakpoint(file, 6);
}
@Override
public void testing() throws Exception {
waitForStart();
loadPage(ports[1] + "/test4");
waitForPause();
eval("x").hasValue("1");
stepOver();
waitForPause();
stepOver();
waitForPause();
eval("y").hasValue("1");
resume();
}
});
}
public void testBreakpointLogExpression() throws IOException {
final int[] ports = findFreePorts(2);
runPythonTest(new DjangoEnvTestTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]) {
@Override
public void before() throws Exception {
//setShouldPrintOutput(true);
String file = getFilePath("/templates/test1.html");
checkModuleForFile(getProject(), VirtualFileUtil.findFile(file));
toggleBreakpoint(file, 6);
XDebuggerTestUtil.setBreakpointLogExpression(getProject(), 6, "'x = %d'%x");
useLongTimeout();
}
@Override
public void testing() throws Exception {
waitForStart();
loadPage(ports[1] + "/test1");
waitForPause();
resume();
waitForOutput("x = 2");
}
});
}
public void testStepInto() throws IOException {
final int[] ports = findFreePorts(2);
runPythonTest(new DjangoEnvTestTask("/djangoDebug", "manage.py", "runserver --noreload ", ports[1]) {
@Override
public void before() throws Exception {
//setShouldPrintOutput(true);
String file = getFilePath("/templates/test5.html");
checkModuleForFile(getProject(), VirtualFileUtil.findFile(file));
toggleBreakpoint(file, 5);
}
@Override
public void testing() throws Exception {
waitForStart();
loadPage(ports[1] + "/test5");
waitForPause();
stepInto();
waitForPause();
stepOver();
waitForPause();
eval("res").hasValue("'Result'");
stepOver();
waitForPause();
eval("name").hasValue("'TemplateDebugging5'");
}
});
}
private static void addDjangoExceptionBreakpoint(IdeaProjectTestFixture fixture) {
XDebuggerTestUtil.addBreakpoint(fixture.getProject(), DjangoExceptionBreakpointType.class, new DjangoExceptionBreakpointProperties());
}
public static int[] findFreePorts(int count)
throws IOException {
ServerSocket[] servers = new ServerSocket[count];
int[] port = new int[count];
for (int i = 0; i < count; i++) {
servers[i] = new ServerSocket(0);
port[i] = servers[i].getLocalPort();
}
for (int i = 0; i < count; i++) {
servers[i].close();
}
return port;
}
public void testBreakpointStopAndEvalInAutoReloadMode() throws IOException {
final int[] ports = findFreePorts(4);
BreakpointStopAndEvalTask testTask = new BreakpointStopAndEvalTask("/djangoDebug", "manage.py", "runserver ", ports[3]) {
@Override
public void before() throws Exception {
super.before();
useLongTimeout();
}
@Override
public Set<String> getTags() {
Set<String> tags = Sets.newHashSet(super.getTags());
tags.add("-django13"); //Django 1.3 doesn't work in reload mode on Unix
return tags;
}
};
//testTask.setShouldPrintOutput(true);
testTask.setMultiprocessDebug(true);
runPythonTest(testTask);
}
}
@@ -0,0 +1,155 @@
package com.jetbrains.env.django;
import com.google.common.collect.Lists;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.django.facet.DjangoFacet;
import com.jetbrains.django.facet.DjangoFacetConfiguration;
import com.jetbrains.django.testRunner.DjangoTestsConfigurationType;
import com.jetbrains.django.testRunner.DjangoTestsRunConfiguration;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.python.packaging.PyExternalProcessException;
import com.jetbrains.python.packaging.PyPackage;
import com.jetbrains.python.packaging.PyPackageManager;
import com.jetbrains.python.packaging.PyRequirement;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* User : ktisha
*/
public class DjangoTestRunnerTest extends PyEnvTestCase {
private static void doTest(@NotNull final String output, @NotNull final String testDataPath) {
final String[] splittedOutput = output.split("\\n");
final ArrayList<String> outputList = Lists.newArrayList();
boolean add = false;
for (String s : splittedOutput) {
if ("sys.path end".equals(s)) add = false;
if (add) outputList.add(norm(s));
if ("sys.path start".equals(s)) add = true;
}
assertEquals(outputList.indexOf(testDataPath),
outputList.lastIndexOf(testDataPath));
}
private static String norm(String testDataPath) {
return FileUtil.toSystemIndependentName(testDataPath);
}
private void doTest(@Nullable final String projectRoot, @Nullable final String settings,
@Nullable final String markAsSource, @Nullable final String customSettings) {
final String name = getTestName(false);
runPythonTest(new DjangoTestRunnerTestTask() {
@Override
public ConfigurationFactory getFactory() {
return DjangoTestsConfigurationType.getInstance().getConfigurationFactories()[0];
}
@Override
protected void configure(AbstractPythonRunConfiguration config) {
String target = "myapp.SimpleTest";
try {
final PyPackage django = PyPackageManager.getInstance(config.getSdk()).findInstalledPackage("django");
if (django != null) {
if (django.matches(PyRequirement.fromStringGuaranteed("django>=1.6a"))) {
target = "myapp.tests.SimpleTest";
}
}
}
catch (PyExternalProcessException ignored) {
}
((DjangoTestsRunConfiguration)config).setTarget(target);
if (customSettings != null)
((DjangoTestsRunConfiguration)config).setSettingsFile(getTestDataPath() + customSettings);
((DjangoTestsRunConfiguration)config).useCustomSettings(true);
}
@Override
protected List<String> getContentRoots() {
return markAsSource == null ? Lists.<String>newArrayList() : Lists.newArrayList(markAsSource);
}
@Override
public void before() throws Exception {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
final Module module = myFixture.getModule();
final DjangoFacet djangoFacet = DjangoFacet.getInstance(module);
if (djangoFacet != null && projectRoot != null && settings != null) {
final DjangoFacetConfiguration configuration = djangoFacet.getConfiguration();
configuration.setProjectRootPath(getTestDataPath() + projectRoot);
configuration.setSettingsFilePath(settings);
}
}
});
}
public void testing() throws Exception {
waitForOutput("Process finished with exit code 0");
doTest(output(), norm(getTestDataPath()));
}
@Override
String getTestName() {
return name;
}
});
}
public void testDjango11() {
doTest();
}
public void testDjango12() {
doTest("", "settings.py", "", null);
}
public void testDjango13() {
doTest();
}
private void doTest() {
doTest(null, null, null, null);
}
public void testDjango14() {
doTest("", "Django14/settings.py", null, null);
}
public void testDjango15() {
doTest("", "Django15/settings.py", null, null);
}
public void testRoot13() {
doTest("/Django13", "settings.py", null, null);
}
public void testRoot() {
doTest("/DjangoRoot", "DjangoRoot/settings.py", null, null);
}
public void testRootMarked() {
doTest("/DjangoRoot", "DjangoRoot/settings.py", "/DjangoRoot", null);
}
public void testSameNamedDir() {
doTest("/web/SameNamedDir", "settings.py", null, null);
}
public void testCustomSettings() {
doTest(null, null, null, "/custom_settings.py");
}
public void testInstalledApps() {
doTest("/InstalledApps", "/config/settings/installedapps.py", null, "/config/settings/installedapps.py");
}
}
@@ -0,0 +1,21 @@
package com.jetbrains.env.django;
import com.jetbrains.python.fixtures.PyProfessionalTestCase;
/**
* User : ktisha
*/
public abstract class DjangoTestRunnerTestTask extends DjangoManageTestTask {
@Override
protected String getTestDataPath() {
return PyProfessionalTestCase.getProfessionalTestDataPath() + "/django/testRunner/" + getTestName();
}
abstract String getTestName();
@Override
protected String getSubcommand() {
return "validate";
}
}
@@ -0,0 +1,100 @@
package com.jetbrains.env.python;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.python.console.PyConsoleTask;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
/**
* @author traff
*/
public class IPythonConsoleTest extends PyEnvTestCase {
public void testQuestion() throws Exception {
runPythonTest(new IPythonTask() {
@Override
public void testing() throws Exception {
exec("import multiprocessing");
exec("multiprocessing?");
waitForOutput("Type:", "module");
}
});
}
public void testParsing() throws Exception {
runPythonTest(new IPythonTask() {
@Override
public void testing() throws Exception {
waitForReady();
addTextToEditor("sys?");
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
PsiFile psi =
PsiDocumentManager.getInstance(getProject())
.getPsiFile(getConsoleView().getLanguageConsole().getConsoleEditor().getDocument());
Assert.assertThat("No errors expected", getErrors(psi), Matchers.empty());
}
});
}
});
}
@NotNull
private static Collection<String> getErrors(PsiFile psi) { //TODO: NotNull?
if (!PsiTreeUtil.hasErrorElements(psi)) {
return Collections.emptyList();
}
return Collections2.transform(PsiTreeUtil.findChildrenOfType(psi, PsiErrorElement.class), new Function<PsiErrorElement, String>() {
@Override
public String apply(PsiErrorElement input) {
return input.getErrorDescription();
}
});
}
public void testParsingNoIPython() throws Exception {
runPythonTest(new IPythonTask() {
@Override
public void testing() throws Exception {
waitForReady();
addTextToEditor("sys?");
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
PsiFile psi =
PsiDocumentManager.getInstance(getProject()).getPsiFile(getConsoleView().getLanguageConsole().getConsoleEditor().getDocument());
//TreeUtil.ensureParsed(psi.getNode());
assertTrue(PsiTreeUtil.hasErrorElements(psi));
}
});
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("-ipython");
}
});
}
private static class IPythonTask extends PyConsoleTask {
@Override
public Set<String> getTags() {
return ImmutableSet.of("ipython");
}
}
}
@@ -0,0 +1,83 @@
package com.jetbrains.env.python;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PsiTestUtil;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.inspections.PyPackageRequirementsInspection;
import com.jetbrains.python.sdkTools.SdkCreationType;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* @author vlan
*/
public class PyPackageRequirementsInspectionTest extends PyEnvTestCase {
public static final ImmutableSet<String> TAGS = ImmutableSet.of("requirements");
public void testPartiallySatisfiedRequirementsTxt() {
doTest("test1.py");
}
public void testPartiallySatisfiedSetupPy() {
doTest("test1.py");
}
public void testImportsNotInRequirementsTxt() {
doTest("test1.py");
}
public void testDuplicateInstallAndTests() {
doTest("test1.py");
}
private void doTest(@NotNull final String filename) {
final String dir = getTestName(false);
runPythonTest(new PyExecutionFixtureTestTask() {
@Override
protected String getTestDataPath() {
return PythonTestUtil.getTestDataPath() + "/inspections/PyPackageRequirementsInspection";
}
@Override
public void runTestOn(String sdkHome) throws Exception {
myFixture.enableInspections(PyPackageRequirementsInspection.class);
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_ONLY);
final String perSdkDir = Integer.toHexString(System.identityHashCode(sdk));
final VirtualFile root = myFixture.copyDirectoryToProject(dir, perSdkDir);
assertNotNull(root);
final Module module = myFixture.getModule();
setupModuleSdk(module, sdk, root);
try {
final VirtualFile file = root.findFileByRelativePath(filename);
assertNotNull(file);
edt(new Runnable() {
@Override
public void run() {
myFixture.testHighlighting(true, true, true, file);
}
});
}
finally {
PsiTestUtil.removeAllRoots(module, sdk);
}
}
@Override
public Set<String> getTags() {
return TAGS;
}
});
}
private static void setupModuleSdk(@NotNull Module module, @NotNull Sdk sdk, @NotNull VirtualFile root) {
ModuleRootModificationUtil.setModuleSdk(module, sdk);
PsiTestUtil.addContentRoot(module, root);
}
}
@@ -0,0 +1,164 @@
package com.jetbrains.env.python;
import com.google.common.collect.Sets;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.env.PyTestTask;
import com.jetbrains.python.packaging.*;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor;
import com.jetbrains.python.sdkTools.SdkCreationType;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author vlan
*/
public class PyPackagingTest extends PyEnvTestCase {
@Override
public void runPythonTest(PyTestTask testTask) {
if (UsefulTestCase.IS_UNDER_TEAMCITY && SystemInfo.isWindows) {
return; //Don't run under Windows as after deleting from created virtualenvs original interpreter got spoiled
}
super.runPythonTest(testTask);
}
public void testGetPackages() {
runPythonTest(new PyPackagingTestTask() {
@Override
public void runTestOn(String sdkHome) throws Exception {
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
List<PyPackage> packages = null;
try {
packages = ((PyPackageManagerImpl)PyPackageManager.getInstance(sdk)).getPackages();
}
catch (PyExternalProcessException e) {
final int retcode = e.getRetcode();
if (retcode != PyPackageManagerImpl.ERROR_NO_PIP && retcode != PyPackageManagerImpl.ERROR_NO_SETUPTOOLS) {
fail(String.format("Error for interpreter '%s': %s", sdk.getHomePath(), e.getMessage()));
}
}
if (packages != null) {
assertTrue(packages.size() > 0);
for (PyPackage pkg : packages) {
assertTrue(pkg.getName().length() > 0);
}
}
}
});
}
public void testCreateVirtualEnv() {
runPythonTest(new PyPackagingTestTask() {
@Override
public void runTestOn(String sdkHome) throws Exception {
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
try {
final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
// virtualenv >= 0.10 supports Python >= 2.6
if (languageLevel.isOlderThan(LanguageLevel.PYTHON26)) {
return;
}
final File tempDir = FileUtil.createTempDirectory(getTestName(false), null);
final File venvDir = new File(tempDir, "venv");
final String venvSdkHome = ((PyPackageManagerImpl)PyPackageManagerImpl.getInstance(sdk)).createVirtualEnv(venvDir.toString(),
false);
final Sdk venvSdk = createTempSdk(venvSdkHome, SdkCreationType.EMPTY_SDK);
assertNotNull(venvSdk);
assertTrue(PythonSdkType.isVirtualEnv(venvSdk));
assertInstanceOf(PythonSdkFlavor.getPlatformIndependentFlavor(venvSdk.getHomePath()), VirtualEnvSdkFlavor.class);
final List<PyPackage> packages = ((PyPackageManagerImpl)PyPackageManagerImpl.getInstance(venvSdk)).getPackages();
final PyPackage setuptools = findPackage("setuptools", packages);
assertNotNull(setuptools);
assertEquals("setuptools", setuptools.getName());
assertEquals(PyPackageManagerImpl.SETUPTOOLS_VERSION, setuptools.getVersion());
final PyPackage pip = findPackage("pip", packages);
assertNotNull(pip);
assertEquals("pip", pip.getName());
assertEquals(PyPackageManagerImpl.PIP_VERSION, pip.getVersion());
}
catch (IOException e) {
throw new RuntimeException(e);
}
catch (PyExternalProcessException e) {
throw new RuntimeException(String.format("Error for interpreter '%s': %s", sdk.getHomePath(), e.getMessage()), e);
}
}
});
}
public void testInstallPackage() {
runPythonTest(new PyPackagingTestTask() {
@Override
public void runTestOn(String sdkHome) throws Exception {
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
try {
final File tempDir = FileUtil.createTempDirectory(getTestName(false), null);
final File venvDir = new File(tempDir, "venv");
final String venvSdkHome = ((PyPackageManagerImpl)PyPackageManager.getInstance(sdk)).createVirtualEnv(venvDir.getPath(), false);
final Sdk venvSdk = createTempSdk(venvSdkHome, SdkCreationType.EMPTY_SDK);
assertNotNull(venvSdk);
final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManager.getInstance(venvSdk);
final List<PyPackage> packages1 = manager.getPackages();
// TODO: Install Markdown from a local file
manager.install(list(PyRequirement.fromString("Markdown<2.2"),
new PyRequirement("httplib2")), Collections.<String>emptyList());
final List<PyPackage> packages2 = manager.getPackages();
final PyPackage markdown2 = findPackage("Markdown", packages2);
assertNotNull(markdown2);
assertTrue(markdown2.isInstalled());
final PyPackage pip1 = findPackage("pip", packages1);
assertNotNull(pip1);
assertEquals("pip", pip1.getName());
assertEquals(PyPackageManagerImpl.PIP_VERSION, pip1.getVersion());
manager.uninstall(list(pip1));
final List<PyPackage> packages3 = manager.getPackages();
final PyPackage pip2 = findPackage("pip", packages3);
assertNull(pip2);
}
catch (PyExternalProcessException e) {
new RuntimeException(String.format("Error for interpreter '%s': %s", sdk.getHomePath(), e.getMessage()), e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
});
}
@Nullable
private static PyPackage findPackage(String name, List<PyPackage> packages) {
for (PyPackage pkg : packages) {
if (name.equals(pkg.getName())) {
return pkg;
}
}
return null;
}
private static <T> List<T> list(T... xs) {
return Arrays.asList(xs);
}
private abstract static class PyPackagingTestTask extends PyExecutionFixtureTestTask {
@Override
public Set<String> getTags() {
return Sets.newHashSet("packaging");
}
}
}
@@ -0,0 +1,130 @@
package com.jetbrains.env.python;
import com.google.common.collect.Sets;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.python.console.PyConsoleTask;
import org.junit.Assert;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author traff
*/
public class PythonConsoleTest extends PyEnvTestCase {
public void testConsolePrint() throws Exception {
runPythonTest(new PyConsoleTask() {
@Override
public void testing() throws Exception {
exec("x = 96");
exec("x += 1");
exec("print(1)");
exec("print(x)");
waitForOutput("97");
}
});
}
public void testExecuteMultiline() throws Exception { //PY-4329
runPythonTest(new PyConsoleTask() {
@Override
public void testing() throws Exception {
exec("if True:\n" +
" x=1\n" +
"y=x+100\n" +
"for i in range(1):\n" +
" print(y)\n");
waitForOutput("101");
}
@Override
public Set<String> getTags() {
return Sets.newHashSet("-jython"); //jython doesn't support multiline execution: http://bugs.jython.org/issue2106
}
});
}
public void testInterruptAsync() throws Exception {
runPythonTest(new PyConsoleTask() {
@Override
public void testing() throws Exception {
exec("import time");
execNoWait("for i in range(10000):\n" +
" print(i)\n" +
" time.sleep(0.1)");
waitForOutput("3\n4\n5");
Assert.assertFalse(canExecuteNow());
interrupt();
waitForFinish();
waitForReady();
}
@Override
public Set<String> getTags() {
return Sets.newHashSet("-iron", "-jython");
}
});
}
public void testLineByLineInput() throws Exception {
runPythonTest(new PyConsoleTask() {
@Override
public void testing() throws Exception {
exec("x = 96");
exec("x +=1");
exec("if True:");
exec(" print(x)");
exec("");
exec("");
waitForOutput("97");
}
});
}
public void testVariablesView() throws Exception {
runPythonTest(new PyConsoleTask() {
@Override
public void testing() throws Exception {
exec("x = 1");
exec("print(x)");
waitForOutput("1");
assertTrue("Variable has wrong value",
hasValue("x", "1"));
}
});
}
public void testCompoundVariable() throws Exception {
runPythonTest(new PyConsoleTask() {
@Override
public void testing() throws Exception {
exec("x = [1, 2, 3]");
exec("print(x)");
waitForOutput("[1, 2, 3]");
List<String> values = getCompoundValueChildren(getValue("x"));
Collections.sort(values);
assertContainsElements(values, "1", "2", "3", "3");
}
});
}
public void testChangeVariable() throws Exception {
runPythonTest(new PyConsoleTask() {
@Override
public void testing() throws Exception {
exec("x = 1");
exec("print(x)");
waitForOutput("1");
setValue("x", "2");
assertTrue("Variable has wrong value",
hasValue("x", "2"));
}
});
}
}
@@ -0,0 +1,579 @@
package com.jetbrains.env.python;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.xdebugger.XDebuggerTestUtil;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.python.debug.PyDebuggerTask;
import com.jetbrains.env.ut.PyUnitTestTask;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.console.pydev.PydevCompletionVariant;
import com.jetbrains.python.debugger.PyDebuggerException;
import com.jetbrains.python.debugger.PyExceptionBreakpointProperties;
import com.jetbrains.python.debugger.PyExceptionBreakpointType;
import com.jetbrains.python.debugger.pydev.ProcessDebugger;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import java.util.List;
import java.util.Set;
/**
* @author traff
*/
public class PythonDebuggerTest extends PyEnvTestCase {
public void testBreakpointStopAndEval() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 3);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("i").hasValue("0");
resume();
waitForPause();
eval("i").hasValue("1");
resume();
waitForPause();
eval("i").hasValue("2");
}
});
}
public void testDebugger() {
runPythonTest(new PyUnitTestTask("", "test_debug.py") {
@Override
protected String getTestDataPath() {
return PythonHelpersLocator.getPythonCommunityPath() + "/helpers/pydev";
}
@Override
public void after() {
allTestsPassed();
}
});
}
public void testConditionalBreakpoint() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 3);
XDebuggerTestUtil.setBreakpointCondition(getProject(), 3, "i == 1 or i == 11 or i == 111");
}
@Override
public void testing() throws Exception {
waitForPause();
eval("i").hasValue("1");
resume();
waitForPause();
eval("i").hasValue("11");
resume();
waitForPause();
eval("i").hasValue("111");
}
});
}
public void testDebugConsole() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 3);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("i").hasValue("0");
resume();
waitForPause();
consoleExec("'i=%d'%i");
waitForOutput("'i=1'");
consoleExec("x");
waitForOutput("name 'x' is not defined");
consoleExec("1-;");
waitForOutput("SyntaxError");
resume();
}
private void consoleExec(String command) {
myDebugProcess.consoleExec(command, new ProcessDebugger.DebugCallback<String>() {
@Override
public void ok(String value) {
}
@Override
public void error(PyDebuggerException exception) {
}
});
}
});
}
public void testDebugCompletion() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test4.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 3);
}
@Override
public void testing() throws Exception {
waitForPause();
List<PydevCompletionVariant> list = myDebugProcess.getCompletions("xvalu");
assertEquals(2, list.size());
}
});
}
public void testBreakpointLogExpression() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 3);
XDebuggerTestUtil.setBreakpointLogExpression(getProject(), 3, "'i = %d'%i");
}
@Override
public void testing() throws Exception {
waitForPause();
resume();
waitForOutput("i = 1");
}
});
}
public void testStepOver() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test2.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 5);
}
@Override
public void testing() throws Exception {
waitForPause();
stepOver();
waitForPause();
stepOver();
waitForPause();
eval("z").hasValue("2");
}
});
}
public void testStepInto() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test2.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 5);
}
@Override
public void testing() throws Exception {
waitForPause();
stepInto();
waitForPause();
eval("x").hasValue("1");
stepOver();
waitForPause();
eval("y").hasValue("3");
stepOver();
waitForPause();
eval("z").hasValue("1");
}
});
}
public void testSmartStepInto() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test3.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 14);
}
@Override
public void testing() throws Exception {
waitForPause();
smartStepInto("foo");
waitForPause();
stepOver();
waitForPause();
eval("y").hasValue("4");
}
});
}
public void testSmartStepInto2() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test3.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 18);
toggleBreakpoint(getScriptPath(), 25);
}
@Override
public void testing() throws Exception {
waitForPause();
toggleBreakpoint(getScriptPath(), 18);
smartStepInto("foo");
waitForPause();
eval("a.z").hasValue("1");
}
});
}
public void testInput() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_input.py") {
@Override
public void before() throws Exception {
}
@Override
public void testing() throws Exception {
waitForOutput("print command >");
input("GO!");
waitForOutput("command was GO!");
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("-jython"); //can't run on jython
}
});
}
public void testRunToLine() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_runtoline.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 1);
toggleBreakpoint(getScriptPath(), 7);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("x").hasValue("0");
runToLine(4);
eval("x").hasValue("1");
resume();
waitForPause();
eval("x").hasValue("12");
resume();
waitForOutput("x = 12");
}
});
}
private static void addExceptionBreakpoint(IdeaProjectTestFixture fixture, PyExceptionBreakpointProperties properties) {
XDebuggerTestUtil.addBreakpoint(fixture.getProject(), PyExceptionBreakpointType.class, properties);
}
public void testExceptionBreakpointOnTerminate() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_exceptbreak.py") {
@Override
public void before() throws Exception {
createExceptionBreak(myFixture, true, false, false);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("__exception__[0].__name__").hasValue("'ZeroDivisionError'");
resume();
waitForTerminate();
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("-iron");
}
});
}
private static void createExceptionBreak(IdeaProjectTestFixture fixture,
boolean notifyOnTerminate,
boolean notifyAlways,
boolean notifyOnFirst) {
XDebuggerTestUtil.removeAllBreakpoints(fixture.getProject());
XDebuggerTestUtil.setDefaultBreakpointEnabled(fixture.getProject(), PyExceptionBreakpointType.class, false);
PyExceptionBreakpointProperties properties = new PyExceptionBreakpointProperties("exceptions.ZeroDivisionError");
properties.setNotifyOnTerminate(notifyOnTerminate);
properties.setNotifyAlways(notifyAlways);
properties.setNotifyOnlyOnFirst(notifyOnFirst);
addExceptionBreakpoint(fixture, properties);
properties = new PyExceptionBreakpointProperties("builtins.ZeroDivisionError"); //for python 3
properties.setNotifyOnTerminate(notifyOnTerminate);
properties.setNotifyAlways(notifyAlways);
properties.setNotifyOnlyOnFirst(notifyOnFirst);
addExceptionBreakpoint(fixture, properties);
}
public void testExceptionBreakpointAlways() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_exceptbreak.py") {
@Override
public void before() throws Exception {
createExceptionBreak(myFixture, false, true, false);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("__exception__[0].__name__").hasValue("'ZeroDivisionError'");
resume();
waitForPause();
resume();
waitForPause();
resume();
waitForTerminate();
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("-pypy"); //TODO: fix it for Pypy
}
});
}
public void testExceptionBreakpointOnFirstRaise() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_exceptbreak.py") {
@Override
public void before() throws Exception {
createExceptionBreak(myFixture, false, false, true);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("__exception__[0].__name__").hasValue("'ZeroDivisionError'");
resume();
waitForTerminate();
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("-iron");
}
});
}
public void testMultithreading() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_multithread.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 9);
toggleBreakpoint(getScriptPath(), 13);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("y").hasValue("2");
resume();
waitForPause();
eval("z").hasValue("102");
resume();
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("-pypy"); //TODO: fix that for PyPy
}
});
}
public void testEggDebug() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_egg.py") {
@Override
public void before() throws Exception {
String egg = getFilePath("Adder-0.1.egg");
toggleBreakpointInEgg(egg, "adder/adder.py", 2);
PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(getRunConfiguration().getSdkHome());
if (flavor != null) {
flavor.initPythonPath(Lists.newArrayList(egg), getRunConfiguration().getEnvs());
}
else {
getRunConfiguration().getEnvs().put("PYTHONPATH", egg);
}
}
@Override
public void testing() throws Exception {
waitForPause();
eval("ret").hasValue("16");
resume();
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("-jython"); //TODO: fix that for Jython if anybody needs it
}
});
}
public void testStepOverConditionalBreakpoint() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_stepOverCondition.py") {
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 1);
toggleBreakpoint(getScriptPath(), 2);
XDebuggerTestUtil.setBreakpointCondition(getProject(), 2, "y == 3");
}
@Override
public void testing() throws Exception {
waitForPause();
stepOver();
waitForPause();
eval("y").hasValue("2");
}
});
}
public void testMultiprocess() throws Exception {
runPythonTest(new PyDebuggerTask("/debug", "test_multiprocess.py") {
@Override
protected void init() {
setMultiprocessDebug(true);
}
@Override
public void before() throws Exception {
toggleBreakpoint(getScriptPath(), 9);
}
@Override
public void testing() throws Exception {
waitForPause();
eval("i").hasValue("'Result:OK'");
resume();
waitForOutput("Result:OK");
}
@Override
public Set<String> getTags() {
return Sets.newHashSet("python3");
}
});
}
//TODO: fix me as I don't work properly sometimes (something connected with process termination on agent)
//public void testResume() throws Exception {
// runPythonTest(new PyDebuggerTask("/debug", "Test_Resume.py") {
// @Override
// public void before() throws Exception {
// toggleBreakpoint(getScriptPath(), 2);
// }
//
// @Override
// public void testing() throws Exception {
// waitForPause();
// eval("x").hasValue("1");
// resume();
// waitForPause();
// eval("x").hasValue("2");
// resume();
// }
// });
//}
//TODO: first fix strange hanging of that test
//public void testRemoteDebug() throws Exception {
// runPythonTest(new PyRemoteDebuggerTask("/debug", "test_remote.py") {
// @Override
// public void before() throws Exception {
// }
//
// @Override
// public void testing() throws Exception {
// waitForPause();
// eval("x").hasValue("0");
// stepOver();
// waitForPause();
// eval("x").hasValue("1");
// stepOver();
// waitForPause();
// eval("x").hasValue("2");
// resume();
// }
//
// @Override
// protected void checkOutput(ProcessOutput output) {
// assertEmpty(output.getStderr());
// assertEquals("OK", output.getStdout().trim());
// }
//
// @Override
// public void after() throws Exception {
// stopDebugServer();
// }
// });
//}
//TODO: That doesn't work now: case from test_continuation.py and test_continuation2.py are treated differently by interpreter
// (first line is executed in first case and last line in second)
//public void testBreakOnContinuationLine() throws Exception {
// runPythonTest(new PyDebuggerTask("/debug", "test_continuation.py") {
// @Override
// public void before() throws Exception {
// toggleBreakpoint(getScriptPath(), 13);
// }
//
// @Override
// public void testing() throws Exception {
// waitForPause();
// eval("x").hasValue("0");
// stepOver();
// waitForPause();
// eval("x").hasValue("1");
// stepOver();
// waitForPause();
// eval("x").hasValue("2");
// }
// });
//}
}
@@ -0,0 +1,24 @@
package com.jetbrains.env.python;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.ut.PyUnitTestTask;
import com.jetbrains.python.PythonHelpersLocator;
/**
* @author traff
*/
public class PythonGeneratorTest extends PyEnvTestCase{
public void testGenerator() {
runPythonTest(new PyUnitTestTask("", "test_generator.py") {
@Override
protected String getTestDataPath() {
return PythonHelpersLocator.getPythonCommunityPath() + "/helpers";
}
@Override
public void after() {
allTestsPassed();
}
});
}
}
@@ -0,0 +1,202 @@
package com.jetbrains.env.python;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.env.PyTestTask;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.documentation.PythonDocumentationProvider;
import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.resolve.PythonSdkPathCache;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher;
import com.jetbrains.python.sdk.skeletons.SkeletonVersionChecker;
import com.jetbrains.python.sdkTools.SdkCreationType;
import com.jetbrains.python.toolbox.Maybe;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.Set;
/**
* Heavyweight integration tests of skeletons of Python binary modules.
* <p/>
* An environment test environment must have a 'skeletons' tag in order to be compatible with this test case. No specific packages are
* required currently. Both Python 2 and Python 3 are OK. All platforms are OK. At least one Python 2.6+ environment is required.
*
* @author vlan
*/
public class PythonSkeletonsTest extends PyEnvTestCase {
public static final ImmutableSet<String> TAGS = ImmutableSet.of("skeletons");
public void testBuiltins() {
runTest(new SkeletonsTask() {
@Override
public void runTestOn(@NotNull Sdk sdk) {
// Check the builtin skeleton header
final Project project = myFixture.getProject();
final PyFile builtins = PyBuiltinCache.getBuiltinsForSdk(project, sdk);
assertNotNull(builtins);
final VirtualFile virtualFile = builtins.getVirtualFile();
assertNotNull(virtualFile);
assertTrue(virtualFile.isInLocalFileSystem());
final String path = virtualFile.getPath();
final PySkeletonRefresher.SkeletonHeader header = PySkeletonRefresher.readSkeletonHeader(new File(path));
assertNotNull(header);
final int version = header.getVersion();
assertTrue("Header version must be > 0, currently it is " + version, version > 0);
assertEquals(SkeletonVersionChecker.BUILTIN_NAME, header.getBinaryFile());
// Run inspections on a file that uses builtins
myFixture.configureByFile(getTestName(false) + ".py");
PsiFile expr = myFixture.getFile();
final Module module = ModuleUtil.findModuleForPsiElement(expr);
final Sdk sdkFromModule = PythonSdkType.findPythonSdk(module);
assertNotNull(sdkFromModule);
final Sdk sdkFromPsi = PyBuiltinCache.findSdkForFile(expr.getContainingFile());
final PyFile builtinsFromSdkCache = PythonSdkPathCache.getInstance(project, sdkFromPsi).getBuiltins().getBuiltinsFile();
assertNotNull(builtinsFromSdkCache);
assertEquals(builtins, builtinsFromSdkCache);
final PyFile builtinsFromPsi = PyBuiltinCache.getInstance(expr).getBuiltinsFile();
assertNotNull(builtinsFromPsi);
assertEquals(builtins, builtinsFromPsi);
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
edt(new Runnable() {
@Override
public void run() {
myFixture.checkHighlighting(true, false, false);
}
});
}
});
}
// PY-4349
public void testFakeNamedTuple() {
runTest(new SkeletonsTask() {
@Override
protected void runTestOn(@NotNull Sdk sdk) {
final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
// Named tuples have been introduced in Python 2.6
if (languageLevel.isOlderThan(LanguageLevel.PYTHON26)) {
return;
}
// XXX: A workaround for invalidating VFS cache with the test file copied to our temp directory
LocalFileSystem.getInstance().refresh(false);
// Run inspections on code that uses named tuples
myFixture.configureByFile(getTestName(false) + ".py");
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
edt(new Runnable() {
@Override
public void run() {
myFixture.checkHighlighting(true, false, false);
}
});
}
});
}
public void testKnownPropertiesTypes() {
runTest(new SkeletonsTask() {
@Override
protected void runTestOn(@NotNull Sdk sdk) {
myFixture.configureByText(PythonFileType.INSTANCE,
"expr = slice(1, 2).start\n");
final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getFile());
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
final PyType type = context.getType(expr);
final String actualType = PythonDocumentationProvider.getTypeName(type, context);
assertEquals("int", actualType);
}
});
}
});
}
// PY-9797
public void testReadWriteDeletePropertyDefault() {
runTest(new SkeletonsTask() {
@Override
protected void runTestOn(@NotNull Sdk sdk) {
final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
// We rely on int.real property that is not explicitly annotated in the skeletons generator
if (languageLevel.isOlderThan(LanguageLevel.PYTHON26)) {
return;
}
final Project project = myFixture.getProject();
final PyFile builtins = PyBuiltinCache.getBuiltinsForSdk(project, sdk);
assertNotNull(builtins);
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
final PyClass cls = builtins.findTopLevelClass("int");
assertNotNull(cls);
final Property prop = cls.findProperty("real", true);
assertNotNull(prop);
assertIsNotNull(prop.getGetter());
assertIsNotNull(prop.getSetter());
assertIsNotNull(prop.getDeleter());
}
});
}
private void assertIsNotNull(Maybe<Callable> accessor) {
if (accessor.isDefined()) {
assertNotNull(accessor.valueOrNull());
}
}
});
}
private void runTest(@NotNull PyTestTask task) {
runPythonTest(task);
}
private abstract class SkeletonsTask extends PyExecutionFixtureTestTask {
@Override
protected String getTestDataPath() {
return PythonTestUtil.getTestDataPath() + "/skeletons/";
}
@Override
public void runTestOn(String sdkHome) throws Exception {
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_AND_SKELETONS);
runTestOn(sdk);
}
@Override
public Set<String> getTags() {
return TAGS;
}
protected abstract void runTestOn(@NotNull Sdk sdk);
}
}
@@ -0,0 +1,380 @@
package com.jetbrains.env.python.console;
import com.google.common.collect.Lists;
import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.frame.XValueChildrenList;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.python.console.*;
import com.jetbrains.python.console.pydev.ConsoleCommunicationListener;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
import com.jetbrains.python.sdkTools.SdkCreationType;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import java.util.List;
import java.util.concurrent.Semaphore;
/**
* @author traff
*/
public class PyConsoleTask extends PyExecutionFixtureTestTask {
private boolean myProcessCanTerminate;
protected PyConsoleProcessHandler myProcessHandler;
protected PydevConsoleCommunication myCommunication;
private boolean shouldPrintOutput = false;
private PythonConsoleView myConsoleView;
private Semaphore mySemaphore;
private Semaphore mySemaphore0;
private PydevConsoleExecuteActionHandler myExecuteHandler;
public PyConsoleTask() {
setWorkingFolder(getTestDataPath());
}
public PythonConsoleView getConsoleView() {
return myConsoleView;
}
@Override
public void setUp(final String testName) throws Exception {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
if (myFixture == null) {
PyConsoleTask.super.setUp(testName);
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
@NotNull
protected String output() {
return myConsoleView.getConsole().getHistoryViewer().getDocument().getText();
}
public void setProcessCanTerminate(boolean processCanTerminate) {
myProcessCanTerminate = processCanTerminate;
}
@Override
public void tearDown() throws Exception {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
if (myConsoleView != null) {
disposeConsole();
}
PyConsoleTask.super.tearDown();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
private void disposeConsole() throws InterruptedException {
if (myCommunication != null) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
myCommunication.close();
}
catch (Exception e) {
e.printStackTrace();
}
myCommunication = null;
}
});
}
disposeConsoleProcess();
if (myConsoleView != null) {
new WriteAction() {
@Override
protected void run(@NotNull Result result) throws Throwable {
Disposer.dispose(myConsoleView);
myConsoleView = null;
}
}.execute();
}
}
@Override
public void runTestOn(final String sdkHome) throws Exception {
final Project project = getProject();
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
setProcessCanTerminate(false);
PydevConsoleRunner consoleRunner = PydevConsoleRunner.create(project, sdk, PyConsoleType.PYTHON, getWorkingFolder());
before();
mySemaphore0 = new Semaphore(0);
consoleRunner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
@Override
public void handleConsoleInitialized(LanguageConsoleView consoleView) {
mySemaphore0.release();
}
});
consoleRunner.run();
waitFor(mySemaphore0);
mySemaphore = new Semaphore(0);
myConsoleView = consoleRunner.getConsoleView();
myProcessHandler = (PyConsoleProcessHandler)consoleRunner.getProcessHandler();
myExecuteHandler = (PydevConsoleExecuteActionHandler)consoleRunner.getConsoleExecuteActionHandler();
myCommunication = consoleRunner.getPydevConsoleCommunication();
myCommunication.addCommunicationListener(new ConsoleCommunicationListener() {
@Override
public void commandExecuted(boolean more) {
mySemaphore.release();
}
@Override
public void inputRequested() {
}
});
myProcessHandler.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(ProcessEvent event) {
if (event.getExitCode() != 0 && !myProcessCanTerminate) {
Assert.fail("Process terminated unexpectedly\n" + output());
}
}
});
OutputPrinter myOutputPrinter = null;
if (shouldPrintOutput) {
myOutputPrinter = new OutputPrinter();
myOutputPrinter.start();
}
waitForOutput("PyDev console");
try {
testing();
after();
}
finally {
setProcessCanTerminate(true);
if (myOutputPrinter != null) {
myOutputPrinter.stop();
}
disposeConsole();
}
}
private void disposeConsoleProcess() throws InterruptedException {
myProcessHandler.destroyProcess();
waitFor(myProcessHandler);
if (!myProcessHandler.isProcessTerminated()) {
if (!waitFor(myProcessHandler)) {
if (!myProcessHandler.isProcessTerminated()) {
throw new RuntimeException("Cannot stop console process");
}
}
}
myProcessHandler = null;
}
/**
* Waits until all passed strings appear in output.
* If they don't appear in time limit, then exception is raised.
*
* @param string
* @throws InterruptedException
*/
public void waitForOutput(String... string) throws InterruptedException {
int count = 0;
while (true) {
List<String> missing = Lists.newArrayList();
String out = output();
boolean flag = true;
for (String s : string) {
if (!out.contains(s)) {
flag = false;
missing.add(s);
}
}
if (flag) {
break;
}
if (count > 10) {
Assert.fail("Strings: <--\n" + StringUtil.join(missing, "\n---\n") + "-->" + "are not present in output.\n" + output());
}
Thread.sleep(2000);
count++;
}
}
protected void waitForReady() throws InterruptedException {
int count = 0;
while (!myExecuteHandler.isEnabled() || !canExecuteNow()) {
if (count > 10) {
Assert.fail("Console is not ready");
}
Thread.sleep(300);
count++;
}
}
protected boolean canExecuteNow() {
return myExecuteHandler.canExecuteNow();
}
public void setShouldPrintOutput(boolean shouldPrintOutput) {
this.shouldPrintOutput = shouldPrintOutput;
}
private class OutputPrinter {
private Thread myThread;
private int myLen = 0;
public void start() {
myThread = new Thread(new Runnable() {
@Override
public void run() {
doJob();
}
});
myThread.setDaemon(true);
myThread.start();
}
private void doJob() {
try {
while (true) {
printToConsole();
Thread.sleep(500);
}
}
catch (Exception ignored) {
}
}
private synchronized void printToConsole() {
String s = output();
if (s.length() > myLen) {
System.out.print(s.substring(myLen));
}
myLen = s.length();
}
public void stop() {
printToConsole();
myThread.interrupt();
}
}
protected void exec(String command) throws InterruptedException {
waitForReady();
int p = mySemaphore.availablePermits();
myConsoleView.executeInConsole(command);
mySemaphore.acquire(p + 1);
//waitForOutput(">>> " + command);
}
protected boolean hasValue(String varName, String value) throws PyDebuggerException {
PyDebugValue val = getValue(varName);
return val != null && value.equals(val.getValue());
}
protected void setValue(String varName, String value) throws PyDebuggerException {
PyDebugValue val = getValue(varName);
myCommunication.changeVariable(val, value);
}
protected PyDebugValue getValue(String varName) throws PyDebuggerException {
XValueChildrenList l = myCommunication.loadFrame();
if (l == null) {
return null;
}
for (int i = 0; i < l.size(); i++) {
String name = l.getName(i);
if (varName.equals(name)) {
return (PyDebugValue)l.getValue(i);
}
}
return null;
}
protected List<String> getCompoundValueChildren(PyDebugValue value) throws PyDebuggerException {
XValueChildrenList list = myCommunication.loadVariable(value);
List<String> result = Lists.newArrayList();
for (int i = 0; i<list.size(); i++) {
result.add(((PyDebugValue)list.getValue(i)).getValue());
}
return result;
}
protected void input(String text) {
myConsoleView.executeInConsole(text);
}
protected void waitForFinish() throws InterruptedException {
waitFor(mySemaphore);
}
protected void execNoWait(final String command) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
myConsoleView.executeCode(command, null);
}
});
}
protected void interrupt() {
myCommunication.interrupt();
}
public void addTextToEditor(final String text) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
getConsoleView().getLanguageConsole().setInputText(text);
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
}
}
);
}
}
@@ -0,0 +1,361 @@
package com.jetbrains.env.python.debug;
import com.google.common.collect.Sets;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.*;
import com.intellij.xdebugger.frame.XValue;
import com.jetbrains.django.util.VirtualFileUtil;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
import com.jetbrains.python.debugger.PyDebugProcess;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;
import java.util.concurrent.Semaphore;
/**
* @author traff
*/
public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask {
private Set<Pair<String, Integer>> myBreakpoints = Sets.newHashSet();
protected PyDebugProcess myDebugProcess;
protected XDebugSession mySession;
protected Semaphore myPausedSemaphore;
protected Semaphore myTerminateSemaphore;
protected boolean shouldPrintOutput = false;
protected boolean myProcessCanTerminate;
protected void waitForPause() throws InterruptedException, InvocationTargetException {
Assert.assertTrue("Debugger didn't stopped within timeout\nOutput:" + output(), waitFor(myPausedSemaphore));
XDebuggerTestUtil.waitForSwing();
}
protected void waitForTerminate() throws InterruptedException, InvocationTargetException {
setProcessCanTerminate(true);
Assert.assertTrue("Debugger didn't terminated within timeout\nOutput:" + output(), waitFor(myTerminateSemaphore));
XDebuggerTestUtil.waitForSwing();
}
protected void runToLine(int line) throws InvocationTargetException, InterruptedException {
XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
XSourcePosition position = currentSession.getCurrentPosition();
currentSession.runToPosition(XDebuggerUtil.getInstance().createPosition(position.getFile(), line), false);
waitForPause();
}
protected void resume() {
XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
Assert.assertTrue(currentSession.isSuspended());
Assert.assertEquals(0, myPausedSemaphore.availablePermits());
currentSession.resume();
}
protected void stepOver() {
XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
Assert.assertTrue(currentSession.isSuspended());
Assert.assertEquals(0, myPausedSemaphore.availablePermits());
currentSession.stepOver(false);
}
protected void stepInto() {
XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
Assert.assertTrue(currentSession.isSuspended());
Assert.assertEquals(0, myPausedSemaphore.availablePermits());
currentSession.stepInto();
}
protected void smartStepInto(String funcName) {
XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
Assert.assertTrue(currentSession.isSuspended());
Assert.assertEquals(0, myPausedSemaphore.availablePermits());
myDebugProcess.startSmartStepInto(funcName);
}
@NotNull
protected String output() {
if (mySession != null && mySession.getConsoleView() != null) {
PythonDebugLanguageConsoleView pydevConsoleView = (PythonDebugLanguageConsoleView)mySession.getConsoleView();
if (pydevConsoleView != null) {
return XDebuggerTestUtil.getConsoleText(pydevConsoleView.getTextConsole());
}
}
return "Console output not available.";
}
protected void input(String text) {
PrintWriter pw = new PrintWriter(myDebugProcess.getProcessHandler().getProcessInput());
pw.println(text);
pw.flush();
}
private void outputContains(String substring) {
Assert.assertTrue(output().contains(substring));
}
public void setProcessCanTerminate(boolean processCanTerminate) {
myProcessCanTerminate = processCanTerminate;
}
protected void clearAllBreakpoints() {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
XDebuggerTestUtil.removeAllBreakpoints(getProject());
}
});
}
/**
* Toggles breakpoint
*
* @param file getScriptPath() or path to script
* @param line starting with 0
*/
protected void toggleBreakpoint(final String file, final int line) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
doToggleBreakpoint(file, line);
}
});
addOrRemoveBreakpoint(file, line);
}
private void addOrRemoveBreakpoint(String file, int line) {
if (myBreakpoints.contains(Pair.create(file, line))) {
myBreakpoints.remove(Pair.create(file, line));
}
else {
myBreakpoints.add(Pair.create(file, line));
}
}
protected void toggleBreakpointInEgg(final String file, final String innerPath, final int line) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
VirtualFile f = VirtualFileUtil.findFile(file);
Assert.assertNotNull(f);
final VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(f);
Assert.assertNotNull(jarRoot);
VirtualFile innerFile = jarRoot.findFileByRelativePath(innerPath);
Assert.assertNotNull(innerFile);
XDebuggerTestUtil.toggleBreakpoint(getProject(), innerFile, line);
}
});
addOrRemoveBreakpoint(file, line);
}
public boolean canPutBreakpointAt(Project project, String file, int line) {
VirtualFile vFile = VirtualFileUtil.findFile(file);
Assert.assertNotNull(vFile);
return XDebuggerUtil.getInstance().canPutBreakpointAt(project, vFile, line);
}
private void doToggleBreakpoint(String file, int line) {
Assert.assertTrue(canPutBreakpointAt(getProject(), file, line));
XDebuggerTestUtil.toggleBreakpoint(getProject(), VirtualFileUtil.findFile(file), line);
}
protected Variable eval(String name) throws InterruptedException {
Assert.assertTrue("Eval works only while suspended", mySession.isSuspended());
XValue var = XDebuggerTestUtil.evaluate(mySession, name).first;
Assert.assertNotNull("There is no variable named " + name, var);
return new Variable(var);
}
protected void setVal(String name, String value) throws InterruptedException, PyDebuggerException {
XValue var = XDebuggerTestUtil.evaluate(mySession, name).first;
myDebugProcess.changeVariable((PyDebugValue)var, value);
}
public void waitForOutput(String ... string) throws InterruptedException {
long started = System.currentTimeMillis();
while (!containsOneOf(output(), string)) {
if (System.currentTimeMillis() - started > myTimeout) {
Assert.fail("None of '" + StringUtil.join(string, ", ") + "'" + " is not present in output.\n" + output());
}
Thread.sleep(2000);
}
}
protected boolean containsOneOf(String output, String[] strings) {
for (String s: strings) {
if (output.contains(s)) {
return true;
}
}
return false;
}
public void setShouldPrintOutput(boolean shouldPrintOutput) {
this.shouldPrintOutput = shouldPrintOutput;
}
@Override
public void setUp(final String testName) throws Exception {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
if (myFixture == null) {
PyBaseDebuggerTask.super.setUp(testName);
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
@Override
public void tearDown() throws Exception {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
try {
if (mySession != null) {
finishSession();
}
PyBaseDebuggerTask.super.tearDown();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
protected void finishSession() throws InterruptedException {
disposeDebugProcess();
if (mySession != null) {
new WriteAction() {
protected void run(Result result) throws Throwable {
mySession.stop();
}
}.execute();
waitFor(mySession.getDebugProcess().getProcessHandler()); //wait for process termination after session.stop() which is async
XDebuggerTestUtil.disposeDebugSession(mySession);
mySession = null;
myDebugProcess = null;
myPausedSemaphore = null;
}
}
protected abstract void disposeDebugProcess() throws InterruptedException;
protected void doTest(@Nullable OutputPrinter myOutputPrinter) throws InterruptedException {
try {
testing();
after();
}
catch (Throwable e) {
throw new RuntimeException(output(), e);
}
finally {
clearAllBreakpoints();
setProcessCanTerminate(true);
if (myOutputPrinter != null) {
myOutputPrinter.stop();
}
finishSession();
}
}
protected static class Variable {
private final XTestValueNode myValueNode;
public Variable(XValue value) throws InterruptedException {
myValueNode = XDebuggerTestUtil.computePresentation(value);
}
public Variable hasValue(String value) {
Assert.assertEquals(value, myValueNode.myValue);
return this;
}
public Variable hasType(String type) {
Assert.assertEquals(type, myValueNode.myType);
return this;
}
public Variable hasName(String name) {
Assert.assertEquals(name, myValueNode.myName);
return this;
}
}
public class OutputPrinter {
private Thread myThread;
public void start() {
myThread = new Thread(new Runnable() {
@Override
public void run() {
doJob();
}
});
myThread.setDaemon(true);
myThread.start();
}
private void doJob() {
int len = 0;
try {
while (true) {
String s = output();
if (s.length() > len) {
System.out.print(s.substring(len));
}
len = s.length();
Thread.sleep(500);
}
}
catch (Exception e) {
}
}
public void stop() {
myThread.interrupt();
}
}
}
@@ -0,0 +1,211 @@
package com.jetbrains.env.python.debug;
import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.KillableColoredProcessHandler;
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.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.xdebugger.*;
import com.jetbrains.python.debugger.PyDebugProcess;
import com.jetbrains.python.debugger.PyDebugRunner;
import com.jetbrains.python.run.PythonCommandLineState;
import com.jetbrains.python.run.PythonConfigurationType;
import com.jetbrains.python.run.PythonRunConfiguration;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.Semaphore;
/**
* @author traff
*/
public class PyDebuggerTask extends PyBaseDebuggerTask {
private boolean myMultiprocessDebug = false;
private PythonRunConfiguration myRunConfiguration;
public PyDebuggerTask() {
init();
}
public PyDebuggerTask(String workingFolder, String scriptName, String scriptParameters) {
setWorkingFolder(getTestDataPath() + workingFolder);
setScriptName(scriptName);
setScriptParameters(scriptParameters);
init();
}
public PyDebuggerTask(String workingFolder, String scriptName) {
this(workingFolder, scriptName, null);
}
protected void init() {
}
public void runTestOn(String sdkHome) throws Exception {
final Project project = getProject();
final ConfigurationFactory factory = PythonConfigurationType.getInstance().getConfigurationFactories()[0];
final RunnerAndConfigurationSettings settings =
RunManager.getInstance(project).createRunConfiguration("test", factory);
myRunConfiguration = (PythonRunConfiguration)settings.getConfiguration();
myRunConfiguration.setSdkHome(sdkHome);
myRunConfiguration.setScriptName(getScriptPath());
myRunConfiguration.setWorkingDirectory(getWorkingFolder());
myRunConfiguration.setScriptParameters(getScriptParameters());
new WriteAction() {
@Override
protected void run(Result result) throws Throwable {
RunManagerEx.getInstanceEx(project).addConfiguration(settings, false);
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(settings);
Assert.assertSame(settings, RunManagerEx.getInstanceEx(project).getSelectedConfiguration());
}
}.execute();
final PyDebugRunner runner = (PyDebugRunner)ProgramRunnerUtil.getRunner(DefaultDebugExecutor.EXECUTOR_ID, settings);
Assert.assertTrue(runner.canRun(DefaultDebugExecutor.EXECUTOR_ID, myRunConfiguration));
final Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
final ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, settings, project);
final PythonCommandLineState pyState = (PythonCommandLineState)myRunConfiguration.getState(executor, env);
assert pyState != null;
pyState.setMultiprocessDebug(isMultiprocessDebug());
final ServerSocket serverSocket;
try {
//noinspection SocketOpenedButNotSafelyClosed
serverSocket = new ServerSocket(0);
}
catch (IOException e) {
throw new ExecutionException("Failed to find free socket port", e);
}
final int serverLocalPort = serverSocket.getLocalPort();
final RunProfile profile = env.getRunProfile();
before();
setProcessCanTerminate(false);
myTerminateSemaphore = new Semaphore(0);
new WriteAction<ExecutionResult>() {
@Override
protected void run(@NotNull Result<ExecutionResult> result) throws Throwable {
final ExecutionResult res =
pyState.execute(executor, PyDebugRunner.createCommandLinePatchers(myFixture.getProject(), pyState, profile, serverLocalPort));
mySession = XDebuggerManager.getInstance(getProject()).
startSession(runner, env, env.getContentToReuse(), new XDebugProcessStarter() {
@NotNull
public XDebugProcess start(@NotNull final XDebugSession session) {
myDebugProcess =
new PyDebugProcess(session, serverSocket, res.getExecutionConsole(), res.getProcessHandler(), isMultiprocessDebug());
myDebugProcess.getProcessHandler().addProcessListener(new ProcessAdapter() {
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
}
@Override
public void processTerminated(ProcessEvent event) {
myTerminateSemaphore.release();
if (event.getExitCode() != 0 && !myProcessCanTerminate) {
Assert.fail("Process terminated unexpectedly\n" + output());
}
}
});
myDebugProcess.getProcessHandler().startNotify();
return myDebugProcess;
}
});
result.setResult(res);
}
}.execute().getResultObject();
OutputPrinter myOutputPrinter = null;
if (shouldPrintOutput) {
myOutputPrinter = new OutputPrinter();
myOutputPrinter.start();
}
myPausedSemaphore = new Semaphore(0);
mySession.addSessionListener(new XDebugSessionAdapter() {
@Override
public void sessionPaused() {
if (myPausedSemaphore != null) {
myPausedSemaphore.release();
}
}
});
doTest(myOutputPrinter);
}
public PythonRunConfiguration getRunConfiguration() {
return myRunConfiguration;
}
private boolean isMultiprocessDebug() {
return myMultiprocessDebug;
}
public void setMultiprocessDebug(boolean multiprocessDebug) {
myMultiprocessDebug = multiprocessDebug;
}
@Override
protected void disposeDebugProcess() throws InterruptedException {
if (myDebugProcess != null) {
ProcessHandler processHandler = myDebugProcess.getProcessHandler();
myDebugProcess.stop();
waitFor(processHandler);
if (!processHandler.isProcessTerminated()) {
killDebugProcess();
if (!waitFor(processHandler)) {
new Throwable("Cannot stop debugger process").printStackTrace();
}
}
}
}
private void killDebugProcess() {
if (myDebugProcess.getProcessHandler() instanceof KillableColoredProcessHandler) {
KillableColoredProcessHandler h = (KillableColoredProcessHandler)myDebugProcess.getProcessHandler();
h.killProcess();
}
else {
myDebugProcess.getProcessHandler().destroyProcess();
}
}
}
@@ -0,0 +1,145 @@
package com.jetbrains.env.python.dotNet;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.python.psi.PyFile;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
/**
* IronPython.NET specific tests
*
* @author Ilya.Kazakevich
*/
public class PyIronPythonTest extends PyEnvTestCase {
/**
* IronPython tag
*/
static final String IRON_TAG = "iron";
public PyIronPythonTest() {
super(IRON_TAG);
}
/**
* Tests skeleton generation
*/
public void testSkeletons() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.java.py",
"com.just.like.java",
"testSkeleton.py",
null
));
}
/**
* Tests skeleton generation with "from" statements
*/
public void testClassFromModule() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.java.py",
"com.just.like.java",
"import_class_from_module.py",
null
));
}
/**
* Tests skeleton generation when imported as alias
*/
public void testClassFromModuleAlias() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.java.py",
"com.just.like.java",
"import_class_from_module_alias.py",
null
));
}
/**
* Tests skeleton generation when module is imported
*/
public void testModuleFromPackage() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.java.py",
"com.just.like.java",
"import_module_from_package.py",
null
));
}
/**
* Tests skeleton generation when several classes are imported
*/
public void testSeveralClasses() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.java.py",
"com.just.like.java",
"import_several_classes_from_module.py",
"com.just.like.java.LikeJavaClass"
));
}
/**
* Tests skeletons for built-in classes. We can't compare files (CLR class may be changed from version to version),
* but we are sure there should be class System.Web.AspNetHostingPermissionLevel which is part of public API
*/
public void testImportBuiltInSystem() throws Exception {
final SkeletonTestTask task = new SkeletonTestTask(
null,
"System.Web",
"import_system.py",
null
);
runPythonTest(task);
final PyFile skeleton = task.getGeneratedSkeleton();
new ReadAction() {
@Override
protected void run(@NotNull Result result) throws Throwable {
Assert.assertNotNull("System.Web does not contain class AspNetHostingPermissionLevel. Error generating stub? It has classes " +
skeleton.getTopLevelClasses(),
skeleton.findTopLevelClass("AspNetHostingPermissionLevel"));
}
}.execute();
}
/**
* Test importing of inner classes
*/
public void testImportInnerClass() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.Deep.py",
"SingleNameSpace.Some.Deep",
"inner_class.py",
null
));
}
/**
* Test importing of the whole namespace
*/
public void testWholeNameSpace() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.SingleNameSpace.py",
"SingleNameSpace",
"whole_namespace.py",
null
));
}
/**
* Test importing of single class
*/
public void testSingleClass() throws Exception {
runPythonTest(new SkeletonTestTask(
"dotNet/expected.skeleton.SingleNameSpace.py",
"SingleNameSpace",
"single_class.py",
null
));
}
}
@@ -0,0 +1,142 @@
package com.jetbrains.env.python.dotNet;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ex.QuickFixWrapper;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.inspections.quickfix.GenerateBinaryStubsFix;
import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.sdk.InvalidSdkException;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdkTools.SdkCreationType;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
/**
* Task for test that checks skeleton generation
*
* @author Ilya.Kazakevich
*/
class SkeletonTestTask extends PyExecutionFixtureTestTask {
/**
* Tags for this task to run
*/
private static final Set<String> IRON_TAGS = Sets.newHashSet(PyIronPythonTest.IRON_TAG);
/**
* Number of seconds we wait for skeleton generation external process (should be enough)
*/
private static final int SECONDS_TO_WAIT_FOR_SKELETON_GENERATION = 20;
@Nullable
private final String myExpectedSkeletonFile;
@NotNull
private final String myModuleNameToBeGenerated;
@NotNull
private final String mySourceFileToRunGenerationOn;
@NotNull
private final String myUseQuickFixWithThisModuleOnly;
private PyFile myGeneratedSkeleton;
/**
* @param expectedSkeletonFile if you want test to compare generated result with some file, provide its name.
* Pass null if you do not want to compare result with anything (you may do it yourself with {@link #getGeneratedSkeleton()})
* @param moduleNameToBeGenerated name of module you think we should generate in dotted notation (like "System.Web" or "com.myModule").
* System will wait for skeleton file for this module to be generated
* @param sourceFileToRunGenerationOn Source file where we should run "generate stubs" on. Be sure to place "caret" on appropriate place!
* @param useQuickFixWithThisModuleOnly If there are several quick fixes in code, you may run fix only on this module.
* Pass null if you are sure there would be only one quickfix
*/
SkeletonTestTask(@Nullable final String expectedSkeletonFile,
@NotNull final String moduleNameToBeGenerated,
@NotNull final String sourceFileToRunGenerationOn,
@Nullable final String useQuickFixWithThisModuleOnly) {
myExpectedSkeletonFile = expectedSkeletonFile;
myModuleNameToBeGenerated = moduleNameToBeGenerated.replace('.', '/');
mySourceFileToRunGenerationOn = sourceFileToRunGenerationOn;
myUseQuickFixWithThisModuleOnly = useQuickFixWithThisModuleOnly != null ? useQuickFixWithThisModuleOnly : "";
}
@Override
public void runTestOn(@NotNull final String sdkHome) throws IOException, InvalidSdkException {
final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_ONLY);
final File skeletonsPath = new File(PythonSdkType.getSkeletonsPath(PathManager.getSystemPath(), sdk.getHomePath()));
File skeletonFileOrDirectory = new File(skeletonsPath, myModuleNameToBeGenerated); // File with module skeleton
// Module may be stored in "moduleName.py" or "moduleName/__init__.py"
if (skeletonFileOrDirectory.isDirectory()) {
skeletonFileOrDirectory = new File(skeletonFileOrDirectory, PyNames.INIT_DOT_PY);
}
else {
skeletonFileOrDirectory = new File(skeletonFileOrDirectory.getAbsolutePath() + PyNames.DOT_PY);
}
final File skeletonFile = skeletonFileOrDirectory;
if (skeletonFile.exists()) { // To make sure we do not reuse it
assert skeletonFile.delete() : "Failed to delete file " + skeletonFile;
}
myFixture.copyFileToProject("dotNet/" + mySourceFileToRunGenerationOn, mySourceFileToRunGenerationOn); // File that uses CLR library
myFixture.copyFileToProject("dotNet/PythonLibs.dll", "PythonLibs.dll"); // Library itself
myFixture.copyFileToProject("dotNet/SingleNameSpace.dll", "SingleNameSpace.dll"); // Another library
myFixture.configureByFile(mySourceFileToRunGenerationOn);
myFixture.enableInspections(PyUnresolvedReferencesInspection.class); // This inspection should suggest us to generate stubs
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
PsiDocumentManager.getInstance(myFixture.getProject()).commitAllDocuments();
final String intentionName = PyBundle.message("sdk.gen.stubs.for.binary.modules", myUseQuickFixWithThisModuleOnly);
final IntentionAction intention = myFixture.findSingleIntention(intentionName);
Assert.assertNotNull("No intention found to generate skeletons!", intention);
Assert.assertThat("Intention should be quick fix to run", intention, Matchers.instanceOf(QuickFixWrapper.class));
final LocalQuickFix quickFix = ((QuickFixWrapper)intention).getFix();
Assert.assertThat("Quick fix should be 'generate binary skeletons' fix to run", quickFix,
Matchers.instanceOf(GenerateBinaryStubsFix.class));
final Task fixTask = ((GenerateBinaryStubsFix)quickFix).getFixTask(myFixture.getFile());
fixTask.run(new AbstractProgressIndicatorBase());
}
});
FileUtil.copy(skeletonFile, new File(myFixture.getTempDirPath(), skeletonFile.getName()));
if (myExpectedSkeletonFile != null) {
myFixture.checkResultByFile(skeletonFile.getName(), myExpectedSkeletonFile, false);
}
myGeneratedSkeleton = (PyFile)myFixture.configureByFile(skeletonFile.getName());
}
@Override
public Set<String> getTags() {
return Collections.unmodifiableSet(IRON_TAGS);
}
/**
* @return File for generated skeleton. Call it after {@link #runTestOn(String)} only!
*/
@NotNull
PyFile getGeneratedSkeleton() {
return myGeneratedSkeleton;
}
}
@@ -0,0 +1,5 @@
/**
* IronPython tests. Install IronPython, .NET and add "iron" to "tags.txt" file. Check for more info: http://confluence.jetbrains.com/display/PYINT/Env+Tests
* @author Ilya.Kazakevich
*/
package com.jetbrains.env.python.dotNet;
@@ -0,0 +1,66 @@
package com.jetbrains.env.python.testing;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.ut.PyDocTestTask;
/**
* User : catherine
*/
public class PythonDocTestingTest extends PyEnvTestCase{
public void testUTRunner() {
runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py") {
@Override
public void after() {
assertEquals(3, allTestsCount());
assertEquals(3, passedTestsCount());
allTestsPassed();
}
});
}
public void testClass() {
runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py::FirstGoodTest") {
@Override
public void after() {
assertEquals(1, allTestsCount());
assertEquals(1, passedTestsCount());
}
});
}
public void testMethod() {
runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py::SecondGoodTest::test_passes") {
@Override
public void after() {
assertEquals(1, allTestsCount());
assertEquals(1, passedTestsCount());
}
});
}
public void testFunction() {
runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py::factorial") {
@Override
public void after() {
assertEquals(1, allTestsCount());
assertEquals(1, passedTestsCount());
}
});
}
public void testUTRunner2() {
runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test2.py") {
@Override
public void after() {
assertEquals(3, allTestsCount());
assertEquals(1, passedTestsCount());
assertEquals(2, failedTestsCount());
}
});
}
}
@@ -0,0 +1,33 @@
package com.jetbrains.env.python.testing;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.ut.PyNoseTestTask;
/**
* User : catherine
*/
public class PythonNoseTestingTest extends PyEnvTestCase{
public void testNoseRunner() {
runPythonTest(new PyNoseTestTask("/testRunner/env/nose", "test1.py") {
@Override
public void after() {
assertEquals(3, allTestsCount());
assertEquals(3, passedTestsCount());
allTestsPassed();
}
});
}
public void testNoseRunner2() {
runPythonTest(new PyNoseTestTask("/testRunner/env/nose", "test2.py") {
@Override
public void after() {
assertEquals(8, allTestsCount());
assertEquals(5, passedTestsCount());
assertEquals(3, failedTestsCount());
}
});
}
}
@@ -0,0 +1,33 @@
package com.jetbrains.env.python.testing;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.ut.PyTestTestTask;
/**
* User : catherine
*/
public class PythonPyTestingTest extends PyEnvTestCase{
public void testPytestRunner() {
runPythonTest(new PyTestTestTask("/testRunner/env/pytest", "test1.py") {
@Override
public void after() {
assertEquals(3, allTestsCount());
assertEquals(3, passedTestsCount());
allTestsPassed();
}
});
}
public void testPytestRunner2() {
runPythonTest(new PyTestTestTask("/testRunner/env/pytest", "test2.py") {
@Override
public void after() {
assertEquals(8, allTestsCount());
assertEquals(5, passedTestsCount());
assertEquals(3, failedTestsCount());
}
});
}
}
@@ -0,0 +1,78 @@
package com.jetbrains.env.python.testing;
import com.jetbrains.env.PyEnvTestCase;
import com.jetbrains.env.ut.PyUnitTestTask;
import junit.framework.Assert;
/**
* @author traff
*/
public class PythonUnitTestingTest extends PyEnvTestCase{
public void testUTRunner() {
runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test1.py") {
@Override
public void after() {
Assert.assertEquals(2, allTestsCount());
Assert.assertEquals(2, passedTestsCount());
allTestsPassed();
}
});
}
public void testUTRunner2() {
runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test2.py") {
@Override
public void after() {
assertEquals(3, allTestsCount());
assertEquals(1, passedTestsCount());
assertEquals(2, failedTestsCount());
}
});
}
public void testClass() {
runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test_file.py::GoodTest") {
@Override
public void after() {
assertEquals(1, allTestsCount());
assertEquals(1, passedTestsCount());
}
});
}
public void testMethod() {
runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test_file.py::GoodTest::test_passes") {
@Override
public void after() {
assertEquals(1, allTestsCount());
assertEquals(1, passedTestsCount());
}
});
}
public void testFolder() {
runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test_folder/") {
@Override
public void after() {
assertEquals(5, allTestsCount());
assertEquals(3, passedTestsCount());
}
});
}
public void testDependent() {
runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "dependentTests/test_my_class.py") {
@Override
public void after() {
assertEquals(1, allTestsCount());
assertEquals(1, passedTestsCount());
}
});
}
}
@@ -0,0 +1,226 @@
package com.jetbrains.env.remote;
import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.*;
import com.jetbrains.env.python.debug.PyBaseDebuggerTask;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.debugger.remote.*;
import com.jetbrains.python.debugger.remote.vfs.PyRemotePositionConverter;
import com.jetbrains.python.sdk.PySdkUtil;
import com.jetbrains.python.sdk.PythonEnvUtil;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.Semaphore;
/**
* @author traff
*/
public class PyRemoteDebuggerTask extends PyBaseDebuggerTask {
private Semaphore mySessionInitializedSemaphore;
public PyRemoteDebuggerTask() {
}
public PyRemoteDebuggerTask(String workingFolder, String scriptName, String scriptParameters) {
setWorkingFolder(getTestDataPath() + workingFolder);
setScriptName(scriptName);
setScriptParameters(scriptParameters);
}
public PyRemoteDebuggerTask(String workingFolder, String scriptName) {
this(workingFolder, scriptName, null);
}
public void runTestOn(final String sdkHome) throws Exception {
final Project project = getProject();
final ConfigurationFactory factory = PyRemoteDebugConfigurationType.getInstance().getConfigurationFactories()[0];
final RunnerAndConfigurationSettings settings =
RunManager.getInstance(project).createRunConfiguration("test", factory);
PyRemoteDebugConfiguration config = (PyRemoteDebugConfiguration)settings.getConfiguration();
new WriteAction() {
@Override
protected void run(Result result) throws Throwable {
RunManagerEx.getInstanceEx(project).addConfiguration(settings, false);
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(settings);
Assert.assertSame(settings, RunManagerEx.getInstanceEx(project).getSelectedConfiguration());
}
}.execute();
final PyRemoteDebugRunner runner = (PyRemoteDebugRunner)ProgramRunnerUtil.getRunner(DefaultDebugExecutor.EXECUTOR_ID, settings);
Assert.assertTrue(runner.canRun(DefaultDebugExecutor.EXECUTOR_ID, config));
final Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
final ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, settings, project);
final PyRemoteDebugCommandLineState pyState = (PyRemoteDebugCommandLineState)config.getState(executor, env);
assert pyState != null;
final ServerSocket serverSocket;
final PyRemoteDebugConfiguration conf = (PyRemoteDebugConfiguration)env.getRunProfile();
try {
//noinspection SocketOpenedButNotSafelyClosed
serverSocket = new ServerSocket(conf.getPort());
}
catch (IOException e) {
throw new ExecutionException("Failed to find free socket port", e);
}
setProcessCanTerminate(false);
mySessionInitializedSemaphore = new Semaphore(0);
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
final ExecutionResult res =
pyState.execute(executor, runner);
mySession = XDebuggerManager.getInstance(project).
startSession(runner, env, env.getContentToReuse(), new XDebugProcessStarter() {
@NotNull
public XDebugProcess start(@NotNull final XDebugSession session) {
myDebugProcess =
new PyRemoteDebugProcess(session, serverSocket, res.getExecutionConsole(),
res.getProcessHandler(), null);
myDebugProcess.setPositionConverter(new PyRemotePositionConverter(myDebugProcess, conf.getMappingSettings()));
myDebugProcess.getProcessHandler().addProcessListener(new ProcessAdapter() {
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
}
@Override
public void processTerminated(ProcessEvent event) {
myTerminateSemaphore.release();
if (event.getExitCode() != 0 && !myProcessCanTerminate) {
Assert.fail("Process terminated unexpectedly\n" + output());
}
}
});
myPausedSemaphore = new Semaphore(0);
myTerminateSemaphore = new Semaphore(0);
return myDebugProcess;
}
});
mySession.addSessionListener(new XDebugSessionAdapter() {
@Override
public void sessionPaused() {
if (myPausedSemaphore != null) {
myPausedSemaphore.release();
}
}
});
mySessionInitializedSemaphore.release();
}
catch (ExecutionException e1) {
throw new RuntimeException(e1);
}
}
});
}
});
before();
new Thread(new Runnable() {
@Override
public void run() {
while (myDebugProcess == null || !myDebugProcess.isWaitingForConnection()) {
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
}
}
ProcessOutput output =
PySdkUtil
.getProcessOutput(getWorkingFolder(), new String[]{sdkHome, getScriptPath(), Integer.toString(serverSocket.getLocalPort())},
new String[]{
PythonEnvUtil.PYTHONUNBUFFERED + "=x",
PythonEnvUtil.PYTHONPATH + "=" + PythonHelpersLocator.getHelpersRoot()}, 0);
checkOutput(output);
}
}).start();
OutputPrinter myOutputPrinter = null;
if (shouldPrintOutput)
{
myOutputPrinter = new OutputPrinter();
myOutputPrinter.start();
}
waitFor(mySessionInitializedSemaphore);
doTest(myOutputPrinter);
}
protected void checkOutput(ProcessOutput output) {
}
protected void stopDebugServer() throws InterruptedException {
if (myDebugProcess != null) {
ProcessHandler h = myDebugProcess.getProcessHandler();
h.destroyProcess();
h.detachProcess();
if (!h.isStartNotified()) {
h.startNotify();
}
}
}
protected void disposeDebugProcess() throws InterruptedException {
if (myDebugProcess != null) {
myDebugProcess.stop();
ProcessHandler h = myDebugProcess.getProcessHandler();
if (!h.isProcessTerminated()) {
h.destroyProcess();
if (!waitFor(h)) {
new Throwable("Cannot stop debugger process").printStackTrace();
}
}
}
}
}
@@ -0,0 +1,85 @@
package com.jetbrains.env.remote;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.env.PyEnvTaskRunner;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.env.PyTestTask;
import com.jetbrains.env.python.PythonDebuggerTest;
import com.jetbrains.python.remote.PyRemoteSdkAdditionalData;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author traff
*/
public class PyRemoteDebuggerTest extends PythonDebuggerTest {
@Override
protected void doRunTests(PyTestTask testTask, String testName, List<String> roots) {
if (RUN_REMOTE && PyTestRemoteSdkProvider.shouldRunRemoteSdk(testTask)) {
if (PyTestRemoteSdkProvider.canRunRemoteSdk()) {
PyEnvTaskRunner remoteRunner = new RemoteTaskRunner(roots);
remoteRunner.runTask(testTask, testName);
}
else {
if (PyTestRemoteSdkProvider.shouldFailWhenCantRunRemote()) {
fail("Cant run with remote sdk: password isn't set");
}
}
}
}
private static class RemoteTaskRunner extends PyEnvTaskRunner {
private RemoteTaskRunner(List<String> roots) {
super(roots);
}
@Override
protected String getExecutable(String root, PyTestTask testTask) {
try {
final Sdk sdk = PyTestRemoteSdkProvider.getInstance().getSdk(getProject(testTask), super.getExecutable(root, testTask));
if (ProjectJdkTable.getInstance().findJdk(sdk.getName()) == null) {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ProjectJdkTable.getInstance().addJdk(sdk);
}
});
}
});
}
return ((PyRemoteSdkAdditionalData)sdk.getSdkAdditionalData()).getRemoteSdkCredentials(false).getSdkId();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
@Nullable
public Project getProject(PyTestTask task) {
if (task instanceof PyExecutionFixtureTestTask) {
return ((PyExecutionFixtureTestTask)task).getProject();
}
return null;
}
@Override
protected boolean shouldRun(String root, PyTestTask task) {
return !isJython(super.getExecutable(root, task)); //TODO: make remote tests work for jython
}
@Override
protected String getEnvType() {
return "remote";
}
}
}
@@ -0,0 +1,138 @@
package com.jetbrains.env.remote;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.common.hash.Hashing;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.remote.RemoteCredentialsHolder;
import com.intellij.remote.RemoteSdkException;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.env.PyTestTask;
import com.jetbrains.python.remote.PyRemoteInterpreterManagerImpl;
import com.jetbrains.python.remote.PyRemoteSdkAdditionalData;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
/**
* @author traff
*/
public class PyTestRemoteSdkProvider {
public static final String SSH_PASSWORD = "SSH_PASSWORD";
public static final String LOCAL_SSH_WITHOUT_PASSWORD = "LOCAL_SSH_WITHOUT_PASSWORD";
private final PyRemoteInterpreterManagerImpl myInterpreterManager;
private static final String SSH_USER_NAME = "SSH_USER_NAME";
private Project myProject;
private static PyTestRemoteSdkProvider INSTANCE = null;
public synchronized static PyTestRemoteSdkProvider getInstance() {
if (INSTANCE == null) {
INSTANCE = new PyTestRemoteSdkProvider();
}
return INSTANCE;
}
public PyTestRemoteSdkProvider() {
myInterpreterManager = new PyRemoteInterpreterManagerImpl();
}
private final LoadingCache<String, Sdk> mySdkTable = CacheBuilder.newBuilder()
.build(
new CacheLoader<String, Sdk>() {
@Override
public Sdk load(String key) throws Exception {
return createSdk(key);
}
}
);
public Sdk getSdk(Project project, String sdkPath) throws ExecutionException {
myProject = project;
return mySdkTable.get(sdkPath);
}
private Sdk createSdk(String interpreterPath) throws RemoteSdkException {
try {
PyRemoteSdkAdditionalData data = createRemoteSdkData(interpreterPath);
final Sdk sdk = myInterpreterManager.createRemoteSdk(myProject, data, null, Lists.<Sdk>newArrayList());
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myInterpreterManager.initSdk(sdk, myProject, null);
}
});
return sdk;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static RemoteCredentialsHolder getTestSdkCredentials() {
RemoteCredentialsHolder data = new RemoteCredentialsHolder();
data.setHost("localhost");
data.setPort(22);
data.setUserName(getUserName());
data.setPassword(getPassword());
return data;
}
private static PyRemoteSdkAdditionalData createRemoteSdkData(final String path) throws IOException {
PyRemoteSdkAdditionalData data = new PyRemoteSdkAdditionalData(path);
data.setSshCredentials(getTestSdkCredentials());
data.setInterpreterPath(path);
try {
data.setHelpersPath(getTempHelpersPath(path));
}
catch (IOException e) {
throw new IllegalStateException(e);
}
return data;
}
public static boolean canRunRemoteSdk() {
return isPasswordSpecified();
}
private static boolean isPasswordSpecified() {
return !StringUtil.isEmpty(System.getenv(LOCAL_SSH_WITHOUT_PASSWORD)) || !StringUtil.isEmpty(getPassword());
}
public static boolean shouldFailWhenCantRunRemote() {
return !StringUtil.isEmpty(System.getenv("FAIL_WHEN_CANT_RUN_REMOTE")) || UsefulTestCase.IS_UNDER_TEAMCITY;
}
private static String getTempHelpersPath(@NotNull String interpreterPath) throws IOException {
final File dir = new File("/tmp");
File tmpDir = FileUtil.createTempDirectory(dir, "pycharm_helpers_", "_" + Math.abs(
Hashing.md5().hashUnencodedChars(interpreterPath).asInt()), true);
return tmpDir.getPath();
}
public static String getUserName() {
String userName = System.getenv(SSH_USER_NAME);
return StringUtil.isEmpty(userName) ? System.getProperty("user.name") : userName;
}
public static String getPassword() {
return System.getenv(SSH_PASSWORD);
}
public static boolean shouldRunRemoteSdk(PyTestTask task) {
return SystemInfo.isUnix;
}
}
+24
View File
@@ -0,0 +1,24 @@
package com.jetbrains.env.ut;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.testing.PythonTestConfigurationType;
/**
* User : catherine
*/
public abstract class PyDocTestTask extends PyUnitTestTask {
public PyDocTestTask(String workingFolder, String scriptName, String scriptParameters) {
super(workingFolder, scriptName, scriptParameters);
}
public PyDocTestTask(String workingFolder, String scriptName) {
this(workingFolder, scriptName, null);
}
public void runTestOn(String sdkHome) throws Exception {
final Project project = getProject();
final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_DOCTEST_FACTORY;
runConfiguration(factory, sdkHome, project);
}
}
+32
View File
@@ -0,0 +1,32 @@
package com.jetbrains.env.ut;
import com.google.common.collect.ImmutableSet;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.testing.PythonTestConfigurationType;
import java.util.Set;
/**
* User : catherine
*/
public abstract class PyNoseTestTask extends PyUnitTestTask {
public PyNoseTestTask(String workingFolder, String scriptName, String scriptParameters) {
super(workingFolder, scriptName, scriptParameters);
}
public PyNoseTestTask(String workingFolder, String scriptName) {
this(workingFolder, scriptName, null);
}
public void runTestOn(String sdkHome) throws Exception {
final Project project = getProject();
final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_NOSETEST_FACTORY;
runConfiguration(factory, sdkHome, project);
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("nose");
}
}
+40
View File
@@ -0,0 +1,40 @@
package com.jetbrains.env.ut;
import com.google.common.collect.ImmutableSet;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.testing.AbstractPythonTestRunConfiguration;
import com.jetbrains.python.testing.PythonTestConfigurationType;
import com.jetbrains.python.testing.pytest.PyTestRunConfiguration;
import java.util.Set;
/**
* User : catherine
*/
public abstract class PyTestTestTask extends PyUnitTestTask {
public PyTestTestTask(String workingFolder, String scriptName, String scriptParameters) {
super(workingFolder, scriptName, scriptParameters);
}
public PyTestTestTask(String workingFolder, String scriptName) {
this(workingFolder, scriptName, null);
}
public void runTestOn(String sdkHome) throws Exception {
final Project project = getProject();
final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_PYTEST_FACTORY;
runConfiguration(factory, sdkHome, project);
}
@Override
public Set<String> getTags() {
return ImmutableSet.of("pytest");
}
protected void configure(AbstractPythonTestRunConfiguration config) {
if (config instanceof PyTestRunConfiguration)
((PyTestRunConfiguration)config).setTestToRun(getScriptPath());
}
}
+240
View File
@@ -0,0 +1,240 @@
package com.jetbrains.env.ut;
import com.google.common.collect.Lists;
import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.executors.DefaultRunExecutor;
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.runners.ProgramRunner;
import com.intellij.execution.testframework.Filter;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
import com.intellij.execution.testframework.sm.runner.ui.TestResultsViewer;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.XDebuggerTestUtil;
import com.jetbrains.env.PyExecutionFixtureTestTask;
import com.jetbrains.python.sdk.PythonEnvUtil;
import com.jetbrains.python.sdk.flavors.JythonSdkFlavor;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import com.jetbrains.python.testing.AbstractPythonTestRunConfiguration;
import com.jetbrains.python.testing.PythonTestConfigurationType;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
/**
* @author traff
*/
public abstract class PyUnitTestTask extends PyExecutionFixtureTestTask {
protected ProcessHandler myProcessHandler;
private boolean shouldPrintOutput = false;
private SMTestProxy.SMRootTestProxy myTestProxy;
private boolean mySetUp = false;
private SMTRunnerConsoleView myConsoleView;
private RunContentDescriptor myDescriptor;
private StringBuilder myOutput;
public PyUnitTestTask() {
}
public PyUnitTestTask(String workingFolder, String scriptName, String scriptParameters) {
setWorkingFolder(getTestDataPath() + workingFolder);
setScriptName(scriptName);
setScriptParameters(scriptParameters);
}
public PyUnitTestTask(String workingFolder, String scriptName) {
this(workingFolder, scriptName, null);
}
@Override
public void setUp(final String testName) throws Exception {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
if (myFixture == null) {
PyUnitTestTask.super.setUp(testName);
mySetUp = true;
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
@NotNull
protected String output() {
return myOutput.toString();
}
@Override
public void tearDown() throws Exception {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
try {
if (mySetUp) {
if (myConsoleView != null) {
Disposer.dispose(myConsoleView);
myConsoleView = null;
}
if (myDescriptor != null) {
Disposer.dispose(myDescriptor);
myDescriptor = null;
}
PyUnitTestTask.super.tearDown();
mySetUp = false;
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
);
}
public void runTestOn(String sdkHome) throws Exception {
final Project project = getProject();
final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_UNITTEST_FACTORY;
runConfiguration(factory, sdkHome, project);
}
protected void runConfiguration(ConfigurationFactory factory, String sdkHome, final Project project) throws Exception {
final RunnerAndConfigurationSettings settings =
RunManager.getInstance(project).createRunConfiguration("test", factory);
AbstractPythonTestRunConfiguration config = (AbstractPythonTestRunConfiguration)settings.getConfiguration();
config.setSdkHome(sdkHome);
config.setScriptName(getScriptPath());
config.setWorkingDirectory(getWorkingFolder());
PythonSdkFlavor sdk = PythonSdkFlavor.getFlavor(sdkHome);
if (sdk instanceof JythonSdkFlavor) {
config.setInterpreterOptions(JythonSdkFlavor.getPythonPathCmdLineArgument(Lists.<String>newArrayList(getWorkingFolder())));
}
else {
PythonEnvUtil.addToPythonPath(config.getEnvs(), getWorkingFolder());
}
configure(config);
new WriteAction() {
@Override
protected void run(Result result) throws Throwable {
RunManagerEx.getInstanceEx(project).addConfiguration(settings, false);
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(settings);
Assert.assertSame(settings, RunManagerEx.getInstanceEx(project).getSelectedConfiguration());
}
}.execute();
final ProgramRunner runner = ProgramRunnerUtil.getRunner(DefaultRunExecutor.EXECUTOR_ID, settings);
Assert.assertTrue(runner.canRun(DefaultRunExecutor.EXECUTOR_ID, config));
final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
final ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, settings, project);
before();
final com.intellij.util.concurrency.Semaphore s = new com.intellij.util.concurrency.Semaphore();
s.down();
myOutput = new StringBuilder();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
try {
runner.execute(env, new ProgramRunner.Callback() {
@Override
public void processStarted(RunContentDescriptor descriptor) {
myDescriptor = descriptor;
myProcessHandler = myDescriptor.getProcessHandler();
myProcessHandler.addProcessListener(new ProcessAdapter() {
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
myOutput.append(event.getText());
}
});
myConsoleView = (com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView)descriptor.getExecutionConsole();
myTestProxy = myConsoleView.getResultsViewer().getTestsRootNode();
myConsoleView.getResultsViewer().addEventsListener(new TestResultsViewer.SMEventsAdapter() {
@Override
public void onTestingFinished(TestResultsViewer sender) {
s.up();
}
});
}
});
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
Assert.assertTrue(s.waitFor(60000));
XDebuggerTestUtil.waitForSwing();
assertFinished();
Assert.assertTrue(output(), allTestsCount() > 0);
after();
disposeProcess(myProcessHandler);
}
protected void configure(AbstractPythonTestRunConfiguration config) {
}
public void allTestsPassed() {
Assert.assertEquals(output(), 0, myTestProxy.getChildren(Filter.NOT_PASSED).size());
Assert.assertEquals(output(), 0, failedTestsCount());
}
public int failedTestsCount() {
return myTestProxy.collectChildren(NOT_SUIT.and(Filter.FAILED_OR_INTERRUPTED)).size();
}
public int passedTestsCount() {
return myTestProxy.collectChildren(NOT_SUIT.and(Filter.PASSED)).size();
}
public void assertFinished() {
Assert.assertTrue("State is " + myTestProxy.getMagnitudeInfo().getTitle() + "\n" + output(),
myTestProxy.wasLaunched() && !myTestProxy.wasTerminated());
}
public int allTestsCount() {
return myTestProxy.collectChildren(NOT_SUIT).size();
}
public static final Filter<SMTestProxy> NOT_SUIT = new Filter<SMTestProxy>() {
@Override
public boolean shouldAccept(SMTestProxy test) {
return !test.isSuite();
}
};
}