| 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.PyDebugCallback; |
| 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 testPydevTests_Debugger() { |
| unittests("tests_python/test_debugger.py"); |
| } |
| |
| private void unittests(final String script) { |
| runPythonTest(new PyUnitTestTask("", script) { |
| @Override |
| protected String getTestDataPath() { |
| return PythonHelpersLocator.getPythonCommunityPath() + "/helpers/pydev"; |
| } |
| |
| @Override |
| public void after() { |
| allTestsPassed(); |
| } |
| |
| @Override |
| protected int getTestTimeout() { |
| return 600000; |
| } |
| }); |
| } |
| |
| public void testDebug() { //TODO: merge it into pydev tests |
| unittests("test_debug.py"); |
| } |
| |
| 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 PyDebugCallback<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"); |
| // } |
| // }); |
| //} |
| } |
| |