// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.env.debug; import com.google.common.collect.ImmutableSet; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SdkModificator; import com.intellij.xdebugger.XDebuggerTestUtil; import com.jetbrains.TestEnv; import com.jetbrains.env.EnvTestTagsRequired; import com.jetbrains.env.PyEnvTestCase; import com.jetbrains.python.debugger.settings.PyDebuggerSettings; import com.jetbrains.python.debugger.settings.PySteppingFilter; import com.jetbrains.python.debugger.smartstepinto.PySmartStepIntoVariant; import com.jetbrains.python.tools.sdkTools.SdkCreationType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.Set; public class PythonDebuggerSteppingTest extends PyEnvTestCase { private static class PySmartStepIntoDebuggerTask extends PyDebuggerTask { private final static String RELATIVE_TEST_DATA_PATH = "/debug/stepping"; PySmartStepIntoDebuggerTask(@NotNull String scriptName) { this(RELATIVE_TEST_DATA_PATH, scriptName); } PySmartStepIntoDebuggerTask(@Nullable String relativeTestDataPath, String scriptName) { super(relativeTestDataPath, scriptName); } @Override public void runTestOn(@NotNull String sdkHome, @Nullable Sdk existingSdk) throws Exception { Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_AND_SKELETONS); SdkModificator modificator = sdk.getSdkModificator(); ApplicationManager.getApplication().invokeAndWait(modificator::commitChanges); super.runTestOn(sdk.getHomePath(), sdk); } void assertSmartStepIntoVariants(@NotNull String @NotNull ... expectedFunctionNames) { ReadAction.run(() -> { List variants = getSmartStepIntoVariants(); String[] arr = new String[variants.size()]; for(int i = 0; i < arr.length; i++) { PySmartStepIntoVariant v = (PySmartStepIntoVariant) variants.get(i); arr[i] = v.getFunctionName(); } Assert.assertArrayEquals(expectedFunctionNames, arr); }); } @NotNull @Override public Set getTags() { // Since we're creating an SDK it's a good idea to remove all the heavy stuff. return ImmutableSet.of("-qt", "-tensorflow1", "-tensorflow2"); } } @Test public void testResumeAfterStepping() { // This test case is important for frame evaluation debugging, because we reuse old tracing function for stepping and there were // some problems with switching between frame evaluation and tracing runPythonTest(new PyDebuggerTask("/debug", "test_resume_after_step.py") { @Override public void before() { toggleBreakpoint(getScriptName(), 2); toggleBreakpoint(getScriptName(), 5); toggleBreakpoint(getScriptName(), 12); } @Override public void testing() throws Exception { waitForPause(); eval("a").hasValue("1"); stepOver(); waitForPause(); stepOver(); waitForPause(); eval("c").hasValue("3"); resume(); waitForPause(); eval("d").hasValue("4"); resume(); waitForPause(); eval("t").hasValue("1"); resume(); } }); } @Test public void testStepInto() { runPythonTest(new PyDebuggerTask("/debug", "test2.py") { @Override public void before() { toggleBreakpoint(getFilePath(getScriptName()), 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"); } }); } @Test public void testStepIntoMyCode() { runPythonTest(new PySmartStepIntoDebuggerTask("test_my_code.py") { @Override public void before() { toggleBreakpoint(getFilePath(getScriptName()), 5); toggleBreakpoint(getFilePath(getScriptName()), 7); } @Override public void testing() throws Exception { waitForPause(); stepIntoMyCode(); waitForPause(); eval("x").hasValue("2"); resume(); waitForPause(); eval("x").hasValue("3"); stepIntoMyCode(); waitForPause(); eval("stopped_in_user_file").hasValue("True"); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepInto() { runPythonTest(new PyDebuggerTask("/debug", "test3.py") { @Override public void before() { toggleBreakpoint(getFilePath(getScriptName()), 14); } @Override public void testing() throws Exception { waitForPause(); smartStepInto("foo", 0); waitForPause(); stepOver(); waitForPause(); eval("y").hasValue("4"); } }); } @Test public void testSmartStepInto2() { runPythonTest(new PySmartStepIntoDebuggerTask("/debug", "test3.py") { @Override public void before() { toggleBreakpoint(getFilePath(getScriptName()), 18); toggleBreakpoint(getFilePath(getScriptName()), 25); } @Override public void testing() throws Exception { waitForPause(); removeBreakpoint(getFilePath(getScriptName()), 18); smartStepInto("foo", 0); waitForPause(); assertSmartStepIntoVariants("zoo", "foo"); smartStepInto("foo", 0); waitForPause(); eval("x").hasValue("4"); resume(); waitForPause(); eval("a.z").hasValue("1"); resume(); waitForTerminate(); } @Override public @NotNull Set getTags() { return ImmutableSet.of("-python3.9", "-python3.10", "-python3.11"); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoVariants() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into.py") { @Override public void before() { toggleBreakpoint(1); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("bar", "baz", "bar", "barbaz", "bar", "barbaz", "bar", "baz", "add"); smartStepInto("barbaz", 1); waitForPause(); eval("i").hasValue("42"); stepOver(); waitForPause(); assertSmartStepIntoVariants("bar", "baz", "add"); smartStepInto("baz", 1); waitForPause(); assertSmartStepIntoVariants("bar", "bar"); smartStepInto("bar", 0); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("bar"); smartStepInto("bar", 1); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); eval("y").hasValue("84"); stepOver(); waitForPause(); assertSmartStepIntoVariants("add"); resume(); waitForPause(); assertSmartStepIntoVariants("bar", "baz", "bar", "barbaz", "bar", "barbaz", "bar", "baz", "add"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoWithStepInto() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into.py") { @Override public void before() { toggleBreakpoint(1); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("bar", "baz", "bar", "barbaz", "bar", "barbaz", "bar", "baz", "add"); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("baz", "bar", "barbaz", "bar", "barbaz", "bar", "baz", "add"); smartStepInto("barbaz", 1); waitForPause(); eval("i").hasValue("42"); stepInto(); waitForPause(); assertSmartStepIntoVariants("bar", "baz", "add"); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("baz", "add"); smartStepInto("baz", 1); waitForPause(); smartStepInto("bar", 1); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("add"); stepOver(); waitForPause(); stepOver(); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("bar", "baz", "bar", "barbaz", "bar", "barbaz", "bar", "baz", "add"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoConstructor() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_constructor.py") { @Override public void before() { toggleBreakpoint(8); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("A", "get_x"); smartStepInto("A", 0); waitForPause(); eval("x").hasValue("42"); resume(); waitForTerminate(); } }); } @Test public void testExplicitInitCall() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_explicit_init.py") { @Override public void before() { toggleBreakpoint(11); } @Override public void testing() throws Exception { waitForPause(); stepInto(); waitForPause(); eval("x").hasValue("1"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoChain() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_chain.py") { @Override public void before() { toggleBreakpoint(6); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("f", "f", "f"); smartStepInto("f", 0); waitForPause(); eval("x").hasValue("1"); stepOver(); waitForPause(); assertSmartStepIntoVariants("f", "f"); smartStepInto("f", 1); waitForPause(); eval("x").hasValue("2"); stepOver(); waitForPause(); assertSmartStepIntoVariants("f"); smartStepInto("f", 2); waitForPause(); eval("x").hasValue("3"); stepOver(); waitForPause(); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoCondition() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_condition.py") { @Override public void before() { toggleBreakpoints(13, 18); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants(); // there shouldn't be any stepping variants here resume(); waitForPause(); assertSmartStepIntoVariants("cond1", "cond2"); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoGenExpr() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_genexpr.py") { @Override public void before() { toggleBreakpoint(11); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants(""); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); eval("x").hasValue("0"); stepOver(); waitForPause(); stepOver(); waitForPause(); eval("i").hasValue("11"); stepInto(); waitForPause(); stepInto(); waitForPause(); toggleBreakpoint(11); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoDecorator1() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_decorator1.py") { @Override public void before() { toggleBreakpoint(12); } @Override public void testing() throws Exception { waitForPause(); smartStepInto("f", 1); waitForPause(); eval("x").hasValue("2"); resume(); waitForTerminate(); } }); } @Test public void testSmartStepIntoDecorator2Python3() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_decorator2.py") { @Override public void before() { toggleBreakpoints(15, 26); } @Override public void testing() throws Exception { waitForPause(); toggleBreakpoint(26); assertSmartStepIntoVariants("foo", "foo", "generate_power"); stepOver(); waitForPause(); assertSmartStepIntoVariants("foo", "foo", "generate_power"); smartStepInto("generate_power", 0); waitForPause(); eval("exponent").hasValue("5"); resume(); if (TestEnv.LINUX.isThisOs()) { waitForPause(); resume(); } waitForTerminate(); } @Override public @NotNull Set getTags() { return ImmutableSet.builder().addAll(super.getTags()) .add("-python2.7") .add("-django") .add("-python3.11") // PY-57113 .build(); } }); } @Test public void testSmartStepIntoDecorator2Python2() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_decorator2.py") { @Override public void before() { toggleBreakpoints(15, 26); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("foo", "foo", "generate_power"); stepOver(); waitForPause(); assertSmartStepIntoVariants("foo", "foo", "generate_power"); smartStepInto("generate_power", 0); waitForPause(); toggleBreakpoint(26); eval("exponent").hasValue("5"); resume(); waitForPause(); resume(); waitForTerminate(); } @Override public @NotNull Set getTags() { return ImmutableSet.builder().addAll(super.getTags()).add("python2.7").build(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoNativeFunction() { runPythonTest(new PySmartStepIntoDebuggerTask( "test_smart_step_into_native_function.py") { @Override public void before() { toggleBreakpoint(9); } @Override public void testing() throws Exception { waitForPause(); smartStepInto("f", 0); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("f", "f"); smartStepInto("f", 2); waitForPause(); resume(); waitForPause(); assertSmartStepIntoVariants("f", "f", "f"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoNativeFunctionInReturn() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_native_function_in_return.py") { @Override public void before() { toggleBreakpoint(5); } @Override public void testing() throws Exception { waitForPause(); smartStepInto("f", 0); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("swapcase"); smartStepInto("swapcase", 0); waitForPause(); assertSmartStepIntoVariants("f", "f", "f", "f"); smartStepInto("f", 1); waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("swapcase"); smartStepInto("swapcase", 0); waitForPause(); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoAnotherModule() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_another_module.py") { @Override public void before() { toggleBreakpoint(2); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("A", "get_x"); smartStepInto("A", 0); waitForPause(); eval("x").hasValue("42"); stepOver(); waitForPause(); assertSmartStepIntoVariants("get_x"); smartStepInto("get_x", 0); waitForPause(); eval("self.x").hasValue("42"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoMultiline1() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_multiline1.py") { @Override public void before() { toggleBreakpoint(4); } @Override public void testing() throws Exception { waitForPause(); stepOver(); waitForPause(); assertSmartStepIntoVariants("f", "f", "f", "f", "f"); smartStepInto("f", 2); waitForPause(); eval("x").hasValue("2"); stepOver(); waitForPause(); assertSmartStepIntoVariants("f", "f"); smartStepInto("f", 4); waitForPause(); eval("x").hasValue("4"); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoMultiline2Python3() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_multiline2.py") { @Override public void before() { toggleBreakpoints(20, 25); } @Override public void testing() throws Exception { waitForPause(); toggleBreakpoint(25); assertSmartStepIntoVariants("A", "return_my_lucking_link", "return_my_lucking_payload", "dumps", "do_stuff"); resume(); waitForPause(); resume(); waitForTerminate(); } @Override public @NotNull Set getTags() { return ImmutableSet.builder().addAll(super.getTags()).add("python3").build(); } }); } @Test public void testSmartStepIntoMultiline2Python2() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_multiline2.py") { @Override public void before() { toggleBreakpoints(20, 25); } @Override public void testing() throws Exception { waitForPause(); toggleBreakpoint(25); assertSmartStepIntoVariants("A", "return_my_lucking_link", "return_my_lucking_payload", "dumps", "do_stuff"); resume(); waitForTerminate(); } @Override public @NotNull Set getTags() { return ImmutableSet.builder().addAll(super.getTags()).add("python2.7").build(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoBinaryOperator1() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_binary_operator1.py") { @Override public void before() { toggleBreakpoint(4); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("identity", "identity", "identity", "identity", "identity"); smartStepInto("identity", 4); waitForPause(); eval("x").hasValue("43"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoBinaryOperator2() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_binary_operator2.py") { @Override public void before() { toggleBreakpoint(16); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("__add__", "__sub__", "Point", "__sub__", "Point", "__add__"); smartStepInto("__sub__", 0); waitForPause(); eval("other.x").hasValue("3"); eval("other.y").hasValue("3"); stepOver(); waitForPause(); smartStepInto("Point", 0); waitForPause(); eval("x").hasValue("4"); eval("y").hasValue("4"); stepOver(); waitForPause(); stepOver(); waitForPause(); assertSmartStepIntoVariants("__sub__", "Point", "__add__"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoBinaryOperator3() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_binary_operator3.py") { @Override public void before() { toggleBreakpoint(47); } @Override public void testing() throws Exception { waitForPause(); stepInto(); waitForPause(); assertSmartStepIntoVariants("A", "A", "__add__", "A", "__add__", "A", "__sub__", "A", "__mul__", "identity", "A", "__div__", "A", "__floordiv__", "__mod__", "A", "__pow__"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoComparisonOperator() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_comparison_operator.py") { @Override public void before() { toggleBreakpoint(14); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("A", "A", "__gt__", "A", "__gt__"); smartStepInto("__gt__", 0); waitForPause(); eval("other.a").hasValue("3"); stepOver(); waitForPause(); stepOver(); waitForPause(); assertSmartStepIntoVariants("A", "__gt__"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoUnaryOperator() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_unary_operator.py") { @Override public void before() { toggleBreakpoint(22); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants( "__add__", "__neg__", "__add__", "A", "__pos__", "__add__", "__invert__", "__add__"); smartStepInto("__neg__", 0); waitForPause(); eval("self.x").hasValue("3"); stepInto(); waitForPause(); stepInto(); waitForPause(); stepInto(); waitForPause(); smartStepInto("A", 0); waitForPause(); eval("x").hasValue("-4"); stepOver(); waitForPause(); assertSmartStepIntoVariants("__pos__", "__add__", "__invert__", "__add__"); smartStepInto("__pos__", 0); waitForPause(); eval("self.x").hasValue("-4"); stepOver(); waitForPause(); assertSmartStepIntoVariants("__add__", "__invert__", "__add__"); smartStepInto("__invert__", 0); waitForPause(); eval("self.x").hasValue("1"); resume(); waitForTerminate(); } }); } @EnvTestTagsRequired(tags = "-python3.11") @Test public void testSmartStepIntoInheritancePython3() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_inheritance.py") { @Override public void before() { toggleBreakpoint(14); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("foo", "make_class"); smartStepInto("foo", 0); waitForPause(); stepOver(); waitForPause(); smartStepInto("make_class", 0); waitForPause(); eval("x").hasValue("100"); resume(); if (TestEnv.LINUX.isThisOs()) { // Python interpreter acts a but different on Linux. waitForPause(); resume(); waitForPause(); resume(); } waitForTerminate(); } @Override public @NotNull Set getTags() { return ImmutableSet.builder().addAll(super.getTags()) .add("-python2.7") .add("-django") .build(); } }); } @Test public void testSmartStepIntoInheritancePython2() { runPythonTest(new PySmartStepIntoDebuggerTask("test_smart_step_into_inheritance.py") { @Override public void before() { toggleBreakpoint(14); } @Override public void testing() throws Exception { waitForPause(); assertSmartStepIntoVariants("foo", "make_class"); smartStepInto("foo", 0); waitForPause(); stepOver(); waitForPause(); smartStepInto("make_class", 0); waitForPause(); eval("x").hasValue("100"); resume(); waitForPause(); resume(); waitForPause(); resume(); waitForTerminate(); } @Override public @NotNull Set getTags() { return ImmutableSet.builder().addAll(super.getTags()).add("python2.7").build(); } }); } @Test public void testStepIntoWithThreads() { runPythonTest(new PySmartStepIntoDebuggerTask("test_step_into_with_threads.py") { @Override public void before() { toggleBreakpoint(getFilePath(getScriptName()), 15); toggleBreakpoint(getFilePath(getScriptName()), 17); } @Override public void testing() throws Exception { waitForPause(); stepInto(); waitForPause(); stepOver(); waitForPause(); waitForOutput("foo"); resume(); waitForOutput("bar"); waitForPause(); stepInto(); waitForPause(); stepOver(); waitForPause(); waitForOutput("baz"); resume(); waitForTerminate(); } }); } @Test public void testStepOver() { runPythonTest(new PyDebuggerTask("/debug", "test2.py") { @Override public void before() { toggleBreakpoint(getFilePath(getScriptName()), 5); } @Override public void testing() throws Exception { waitForPause(); stepOver(); waitForPause(); stepOver(); waitForPause(); eval("z").hasValue("2"); } }); } @Test public void testStepOverConditionalBreakpoint() { runPythonTest(new PySmartStepIntoDebuggerTask("test_stepOverCondition.py") { @Override public void before() { toggleBreakpoint(getScriptName(), 1); toggleBreakpoint(getScriptName(), 2); XDebuggerTestUtil.setBreakpointCondition(getProject(), 2, "y == 3"); } @Override public void testing() throws Exception { waitForPause(); stepOver(); waitForPause(); eval("y").hasValue("2"); } }); } @Test public void testStepOverYieldFrom() { runPythonTest(new PySmartStepIntoDebuggerTask("test_step_over_yield.py") { @Override protected void init() { setMultiprocessDebug(true); } @Override public void before() { toggleBreakpoint(getScriptName(), 6); } @Override public void testing() throws Exception { waitForPause(); stepOver(); waitForPause(); eval("a").hasValue("42"); stepOver(); waitForPause(); eval("a").hasValue("42"); stepOver(); waitForPause(); eval("sum").hasValue("6"); resume(); } @NotNull @Override public Set getTags() { return ImmutableSet.builder().addAll(super.getTags()).add("-python2.7").build(); } }); } @Test public void testStepOverAwait() { runPythonTest(new PyDebuggerTask("/debug/stepping", "test_step_over_await.py") { @Override public void before() { toggleBreakpoint(10); } @Override public void testing() throws Exception { waitForPause(); stepOver(); waitForPause(); eval("result").hasValue("3"); stepOver(); waitForPause(); eval("z").hasValue("42"); // check that we haven't got into the `asyncio` machinery resume(); waitForTerminate(); } @Override public @NotNull Set getTags() { return Set.of("-python2.7"); } }); } @Test public void testStepOverOutsideProject() { runPythonTest(new PyDebuggerTask("/debug/stepping/", "test_step_over_outside_project_scope.py") { @Override public void before() { toggleBreakpoint(3); } @Override public void testing() throws Exception { waitForPause(); stepInto(); waitForPause(); stepOver(); waitForPause(); eval("instream").hasValue("'a b c'"); // ensure we're still in the library scope after performing a step over resume(); waitForTerminate(); } }); } @Test public void testSteppingFilter() { runPythonTest(new PySmartStepIntoDebuggerTask("test_stepping_filter.py") { @Override public void before() { toggleBreakpoint(getScriptName(), 4); List filters = new ArrayList<>(); filters.add(new PySteppingFilter(true, "*/test_m?_code.py")); final PyDebuggerSettings debuggerSettings = PyDebuggerSettings.getInstance(); debuggerSettings.setLibrariesFilterEnabled(true); debuggerSettings.setSteppingFiltersEnabled(true); debuggerSettings.setSteppingFilters(filters); } @Override public void doFinally() { final PyDebuggerSettings debuggerSettings = PyDebuggerSettings.getInstance(); debuggerSettings.setLibrariesFilterEnabled(false); debuggerSettings.setSteppingFiltersEnabled(false); } @Override public void testing() throws Exception { waitForPause(); stepInto(); waitForPause(); eval("stopped_in_user_file").hasValue("True"); stepInto(); waitForPause(); eval("stopped_in_user_file").hasValue("True"); } }); } }