Automatically switch client/server mode in debugger tests; PY-78168

(cherry picked from commit 3714877098305edcc4eae4f9761ab176c0112355)

IJ-MR-151881

GitOrigin-RevId: e6c06cfd22fa03964b8373ecd738fec26c7d785f
This commit is contained in:
Aleksandr Sorotskii
2024-12-20 11:52:04 +01:00
committed by intellij-monorepo-bot
parent f5e820f848
commit 4ed6a858d4

View File

@@ -1,6 +1,7 @@
// 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. // 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; package com.jetbrains.env.debug;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor; import com.intellij.execution.Executor;
import com.intellij.execution.RunManager; import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings; import com.intellij.execution.RunnerAndConfigurationSettings;
@@ -14,6 +15,7 @@ import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.xdebugger.*; import com.intellij.xdebugger.*;
import com.jetbrains.python.debugger.PyDebugProcess; import com.jetbrains.python.debugger.PyDebugProcess;
import com.jetbrains.python.debugger.PyDebugRunner; import com.jetbrains.python.debugger.PyDebugRunner;
@@ -26,6 +28,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.junit.Assert; import org.junit.Assert;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
/** /**
@@ -57,6 +61,102 @@ public abstract class PyCustomConfigDebuggerTask extends PyBaseDebuggerTask {
@Override @Override
public void runTestOn(@NotNull String sdkHome, @Nullable Sdk existingSdk) throws Exception { public void runTestOn(@NotNull String sdkHome, @Nullable Sdk existingSdk) throws Exception {
if (Registry.is("python.debug.use.single.port")) {
runTestInClientMode(sdkHome, existingSdk);
}
else {
runTestInServerMode(sdkHome, existingSdk);
}
}
private void runTestInServerMode(@NotNull String sdkHome, @Nullable Sdk existingSdk) throws Exception {
Project project = getProject();
myRunConfiguration = createRunConfiguration(sdkHome, existingSdk);
WriteAction.runAndWait(() -> {
RunManager runManager = RunManager.getInstance(project);
runManager.addConfiguration(mySettings);
runManager.setSelectedConfiguration(mySettings);
Assert.assertSame(mySettings, runManager.getSelectedConfiguration());
});
PyDebugRunner runner = (PyDebugRunner)ProgramRunner.getRunner(getExecutorId(), mySettings.getConfiguration());
Assert.assertTrue(runner.canRun(getExecutorId(), myRunConfiguration));
Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, mySettings, project);
PythonCommandLineState pyState = (PythonCommandLineState)myRunConfiguration.getState(executor, env);
assert pyState != null;
pyState.setMultiprocessDebug(isMultiprocessDebug());
try (ServerSocket serverSocket = new ServerSocket(0)) {
int serverLocalPort = serverSocket.getLocalPort();
RunProfile profile = env.getRunProfile();
createExceptionBreak(myFixture, false, false, false); //turn off exception breakpoints by default
before();
myTerminateSemaphore = new Semaphore(0);
WriteAction.runAndWait(() -> {
myExecutionResult =
pyState.execute(executor, createCommandLinePatchers(runner, pyState, profile, serverLocalPort));
mySession = XDebuggerManager.getInstance(getProject()).
startSession(env, new XDebugProcessStarter() {
@Override
@NotNull
public XDebugProcess start(@NotNull final XDebugSession session) {
myDebugProcess =
new PyDebugProcess(session, serverSocket, myExecutionResult.getExecutionConsole(), myExecutionResult.getProcessHandler(),
isMultiprocessDebug());
myDebugProcess.getProcessHandler().addProcessListener(new ProcessAdapter() {
@Override
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
myOutputBuilder.append(event.getText());
if (outputType == ProcessOutputType.STDERR) {
myStdErrBuilder.append(event.getText());
}
}
@Override
public void processTerminated(@NotNull ProcessEvent event) {
myTerminateSemaphore.release();
if (event.getExitCode() != 0 && !myProcessCanTerminate) {
Assert.fail("Process terminated unexpectedly\n" + myOutputBuilder);
}
}
});
myDebugProcess.getProcessHandler().startNotify();
return myDebugProcess;
}
});
});
myPausedSemaphore = new Semaphore(0);
mySession.addSessionListener(new XDebugSessionListener() {
@Override
public void sessionPaused() {
if (myPausedSemaphore != null) {
myPausedSemaphore.release();
}
}
});
doTest(null);
}
catch (IOException e) {
throw new ExecutionException("Failed to find free socket port", e); // NON-NLS
}
}
private void runTestInClientMode(@NotNull String sdkHome, @Nullable Sdk existingSdk) throws Exception {
Project project = getProject(); Project project = getProject();
myRunConfiguration = createRunConfiguration(sdkHome, existingSdk); myRunConfiguration = createRunConfiguration(sdkHome, existingSdk);
@@ -242,7 +342,8 @@ public abstract class PyCustomConfigDebuggerTask extends PyBaseDebuggerTask {
* Toggles multiple breakpoints with {@link PyDebuggerTask#toggleBreakpoint(String, int)}. * Toggles multiple breakpoints with {@link PyDebuggerTask#toggleBreakpoint(String, int)}.
*/ */
protected void toggleBreakpoints(@NotNull String file, int... lines) { protected void toggleBreakpoints(@NotNull String file, int... lines) {
for(int line : lines) for (int line : lines) {
toggleBreakpoint(file, line); toggleBreakpoint(file, line);
}
} }
} }