diff --git a/python/testData/debug/test_ref.py b/python/testData/debug/test_ref.py new file mode 100644 index 000000000000..032b79cfa69a --- /dev/null +++ b/python/testData/debug/test_ref.py @@ -0,0 +1,7 @@ +t = [1, 2] + +def foo(l): + return len(l) + +print(foo(t)) +t.append(3) diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java index 5a38dfd94195..a3ff326af470 100644 --- a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java @@ -1011,6 +1011,23 @@ public class PythonDebuggerTest extends PyEnvTestCase { }); } + @Test + @Staging + public void testShowReferringObjects() throws Exception { + runPythonTest(new PyDebuggerTask("/debug", "test_ref.py") { + @Override + public void before() throws Exception { + toggleBreakpoint(getFilePath(getScriptName()), 3); + } + + @Override + public void testing() throws Exception { + waitForPause(); + int numberOfReferringObjects = getNumberOfReferringObjects("l"); + assertEquals(3, numberOfReferringObjects); + } + }); + } //TODO: fix me as I don't work properly sometimes (something connected with process termination on agent) @Staging diff --git a/python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java b/python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java index b823feb49f27..ac8084c635c8 100644 --- a/python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java +++ b/python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java @@ -33,12 +33,11 @@ import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.XBreakpointManager; import com.intellij.xdebugger.breakpoints.XLineBreakpoint; import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.frame.XValueChildrenList; 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 com.jetbrains.python.debugger.PyThreadInfo; +import com.jetbrains.python.debugger.*; +import com.jetbrains.python.debugger.pydev.PyDebugCallback; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -256,6 +255,31 @@ public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask { return null; } + protected int getNumberOfReferringObjects(String name) throws PyDebuggerException { + XValue var = XDebuggerTestUtil.evaluate(mySession, name).first; + final PyReferringObjectsValue value = new PyReferringObjectsValue((PyDebugValue)var); + EvaluationCallback callback = new EvaluationCallback(); + + myDebugProcess.loadReferrers(value, new PyDebugCallback() { + @Override + public void ok(XValueChildrenList valueList) { + callback.evaluated(valueList.size()); + } + + @Override + public void error(PyDebuggerException exception) { + callback.errorOccurred(exception.getMessage()); + } + }); + + final Pair result = callback.waitFor(NORMAL_TIMEOUT); + if (result.second != null) { + throw new PyDebuggerException(result.second); + } + + return result.first; + } + protected Variable eval(String name) throws InterruptedException { Assert.assertTrue("Eval works only while suspended", mySession.isSuspended()); XValue var = XDebuggerTestUtil.evaluate(mySession, name).first; @@ -369,6 +393,27 @@ public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask { } } + protected static class EvaluationCallback { + private final Semaphore myFinished = new Semaphore(0); + private int myResult; + private String myErrorMessage; + + public void evaluated(int result) { + myResult = result; + myFinished.release(); + } + + public void errorOccurred(@NotNull String errorMessage) { + myErrorMessage = errorMessage; + myFinished.release(); + } + + public Pair waitFor(long timeoutInMilliseconds) { + Assert.assertTrue("timed out", XDebuggerTestUtil.waitFor(myFinished, timeoutInMilliseconds)); + return Pair.create(myResult, myErrorMessage); + } + } + protected static class Variable { private final XTestValueNode myValueNode;