2 * Copyright 2000-2016 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.debugger;
18 import com.intellij.JavaTestUtil;
19 import com.intellij.debugger.engine.DebugProcessImpl;
20 import com.intellij.debugger.engine.JavaDebugProcess;
21 import com.intellij.debugger.engine.RemoteStateState;
22 import com.intellij.debugger.engine.SuspendContextImpl;
23 import com.intellij.debugger.engine.evaluation.EvaluateException;
24 import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
25 import com.intellij.debugger.engine.events.DebuggerCommandImpl;
26 import com.intellij.debugger.impl.*;
27 import com.intellij.debugger.jdi.StackFrameProxyImpl;
28 import com.intellij.debugger.settings.DebuggerSettings;
29 import com.intellij.debugger.settings.NodeRendererSettings;
30 import com.intellij.debugger.ui.breakpoints.BreakpointManager;
31 import com.intellij.execution.ExecutionException;
32 import com.intellij.execution.Executor;
33 import com.intellij.execution.configurations.*;
34 import com.intellij.execution.executors.DefaultDebugExecutor;
35 import com.intellij.execution.process.ProcessAdapter;
36 import com.intellij.execution.process.ProcessEvent;
37 import com.intellij.execution.process.ProcessHandler;
38 import com.intellij.execution.process.ProcessOutputTypes;
39 import com.intellij.execution.runners.ExecutionEnvironment;
40 import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
41 import com.intellij.execution.runners.ProgramRunner;
42 import com.intellij.openapi.application.ApplicationManager;
43 import com.intellij.openapi.application.ModalityState;
44 import com.intellij.openapi.editor.Document;
45 import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
46 import com.intellij.openapi.module.Module;
47 import com.intellij.openapi.options.SettingsEditor;
48 import com.intellij.openapi.project.Project;
49 import com.intellij.openapi.util.Computable;
50 import com.intellij.openapi.util.InvalidDataException;
51 import com.intellij.openapi.util.Key;
52 import com.intellij.openapi.util.WriteExternalException;
53 import com.intellij.openapi.util.text.StringUtil;
54 import com.intellij.psi.JavaPsiFacade;
55 import com.intellij.psi.PsiClass;
56 import com.intellij.psi.PsiDocumentManager;
57 import com.intellij.psi.PsiFile;
58 import com.intellij.psi.search.GlobalSearchScope;
59 import com.intellij.util.ui.UIUtil;
60 import com.intellij.xdebugger.XDebugProcess;
61 import com.intellij.xdebugger.XDebugProcessStarter;
62 import com.intellij.xdebugger.XDebugSession;
63 import com.intellij.xdebugger.XDebuggerManager;
64 import com.sun.jdi.Location;
65 import org.jdom.Element;
66 import org.jetbrains.annotations.NotNull;
69 import java.lang.reflect.InvocationTargetException;
70 import java.util.StringTokenizer;
72 public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCase {
73 public static final int DEFAULT_ADDRESS = 3456;
74 protected DebuggerSession myDebuggerSession;
77 protected void initApplication() throws Exception {
78 super.initApplication();
79 JavaTestUtil.setupTestJDK();
80 DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = DebuggerSettings.SOCKET_TRANSPORT;
81 DebuggerSettings.getInstance().SKIP_CONSTRUCTORS = false;
82 DebuggerSettings.getInstance().SKIP_GETTERS = false;
83 NodeRendererSettings.getInstance().getClassRenderer().SHOW_DECLARED_TYPE = true;
87 protected void runTest() throws Throwable {
89 if(getDebugProcess() != null) {
90 getDebugProcess().getProcessHandler().startNotify();
91 waitProcess(getDebugProcess().getProcessHandler());
93 //disposeSession(myDebuggerSession);
94 assertNull(DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(getDebugProcess().getProcessHandler()));
95 myDebuggerSession = null;
97 throwExceptionsIfAny();
101 protected void checkTestOutput() throws Exception {
102 getChecker().checkValid(getTestProjectJdk());
105 protected void disposeSession(final DebuggerSession debuggerSession) throws InterruptedException, InvocationTargetException {
106 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
109 debuggerSession.dispose();
115 protected void tearDown() throws Exception {
117 FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();
118 if (myDebugProcess != null) {
119 myDebugProcess.stop(true);
120 myDebugProcess.waitFor();
128 protected void createLocalProcess(String className) throws ExecutionException, InterruptedException, InvocationTargetException {
129 LOG.assertTrue(myDebugProcess == null);
130 myDebuggerSession = createLocalProcess(DebuggerSettings.SOCKET_TRANSPORT, createJavaParameters(className));
131 myDebugProcess = myDebuggerSession.getProcess();
134 protected DebuggerSession createLocalSession(final JavaParameters javaParameters) throws ExecutionException, InterruptedException {
135 createBreakpoints(javaParameters.getMainClass());
136 DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = DebuggerSettings.SOCKET_TRANSPORT;
138 GenericDebuggerRunnerSettings debuggerRunnerSettings = new GenericDebuggerRunnerSettings();
139 debuggerRunnerSettings.LOCAL = true;
141 final RemoteConnection debugParameters = DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerRunnerSettings, false);
143 ExecutionEnvironment environment = new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
144 .runnerSettings(debuggerRunnerSettings)
145 .runProfile(new MockConfiguration())
147 final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(environment){
149 protected JavaParameters createJavaParameters() {
150 return javaParameters;
154 protected GeneralCommandLine createCommandLine() throws ExecutionException {
155 return CommandLineBuilder.createFromJavaParameters(getJavaParameters());
159 ApplicationManager.getApplication().invokeAndWait(new Runnable() {
164 DebuggerManagerEx.getInstanceEx(myProject)
165 .attachVirtualMachine(new DefaultDebugEnvironment(new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
166 .runProfile(new MockConfiguration())
167 .build(), javaCommandLineState, debugParameters, false));
168 XDebuggerManager.getInstance(myProject).startSession(javaCommandLineState.getEnvironment(), new XDebugProcessStarter() {
171 public XDebugProcess start(@NotNull XDebugSession session) {
172 return JavaDebugProcess.create(session, myDebuggerSession);
176 catch (ExecutionException e) {
180 }, ModalityState.defaultModalityState());
181 myDebugProcess = myDebuggerSession.getProcess();
183 myDebugProcess.addProcessListener(new ProcessAdapter() {
185 public void onTextAvailable(ProcessEvent event, Key outputType) {
186 print(event.getText(), outputType);
190 assertNotNull(myDebuggerSession);
191 assertNotNull(myDebugProcess);
193 return myDebuggerSession;
197 protected DebuggerSession createLocalProcess(int transport, final JavaParameters javaParameters) throws ExecutionException, InterruptedException, InvocationTargetException {
198 createBreakpoints(javaParameters.getMainClass());
199 final DebuggerSession[] debuggerSession = new DebuggerSession[]{null};
201 DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = transport;
203 GenericDebuggerRunnerSettings debuggerRunnerSettings = new GenericDebuggerRunnerSettings();
204 debuggerRunnerSettings.LOCAL = true;
205 debuggerRunnerSettings.setDebugPort(String.valueOf(DEFAULT_ADDRESS));
207 ExecutionEnvironment environment = new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
208 .runnerSettings(debuggerRunnerSettings)
209 .runProfile(new MockConfiguration())
211 final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(environment) {
213 protected JavaParameters createJavaParameters() {
214 return javaParameters;
218 protected GeneralCommandLine createCommandLine() throws ExecutionException {
219 return CommandLineBuilder.createFromJavaParameters(getJavaParameters());
223 final RemoteConnection debugParameters =
224 DebuggerManagerImpl.createDebugParameters(javaCommandLineState.getJavaParameters(), debuggerRunnerSettings, true);
226 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
230 debuggerSession[0] = attachVirtualMachine(javaCommandLineState, javaCommandLineState.getEnvironment(), debugParameters, false);
232 catch (ExecutionException e) {
233 fail(e.getMessage());
238 final ProcessHandler processHandler = debuggerSession[0].getProcess().getProcessHandler();
239 debuggerSession[0].getProcess().addProcessListener(new ProcessAdapter() {
241 public void onTextAvailable(ProcessEvent event, Key outputType) {
242 print(event.getText(), outputType);
246 DebugProcessImpl process =
247 (DebugProcessImpl)DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(processHandler);
248 assertNotNull(process);
249 return debuggerSession[0];
253 protected DebuggerSession createRemoteProcess(final int transport, final boolean serverMode, JavaParameters javaParameters)
254 throws ExecutionException, InterruptedException, InvocationTargetException {
255 boolean useSockets = transport == DebuggerSettings.SOCKET_TRANSPORT;
257 RemoteConnection remoteConnection = new RemoteConnection(
260 String.valueOf(DEFAULT_ADDRESS),
263 String launchCommandLine = remoteConnection.getLaunchCommandLine();
265 launchCommandLine = StringUtil.replace(launchCommandLine, RemoteConnection.ONTHROW, "");
266 launchCommandLine = StringUtil.replace(launchCommandLine, RemoteConnection.ONUNCAUGHT, "");
268 launchCommandLine = StringUtil.replace(launchCommandLine, "suspend=n", "suspend=y");
270 println(launchCommandLine, ProcessOutputTypes.SYSTEM);
272 for(StringTokenizer tokenizer = new StringTokenizer(launchCommandLine);tokenizer.hasMoreTokens();) {
273 String token = tokenizer.nextToken();
274 javaParameters.getVMParametersList().add(token);
277 GeneralCommandLine commandLine = CommandLineBuilder.createFromJavaParameters(javaParameters);
280 DebuggerSession debuggerSession;
283 debuggerSession = attachVM(remoteConnection, false);
284 commandLine.createProcess();
286 commandLine.createProcess();
287 debuggerSession = attachVM(remoteConnection, true);
290 ProcessHandler processHandler = debuggerSession.getProcess().getProcessHandler();
291 DebugProcessImpl process = (DebugProcessImpl)DebuggerManagerEx.getInstanceEx(myProject)
292 .getDebugProcess(processHandler);
294 assertNotNull(process);
295 return debuggerSession;
298 protected DebuggerSession attachVM(final RemoteConnection remoteConnection, final boolean pollConnection)
299 throws InvocationTargetException, InterruptedException {
300 final RemoteState remoteState = new RemoteStateState(myProject, remoteConnection);
302 final DebuggerSession[] debuggerSession = new DebuggerSession[1];
303 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
307 debuggerSession[0] = attachVirtualMachine(remoteState, new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
308 .runProfile(new MockConfiguration())
309 .build(), remoteConnection, pollConnection);
311 catch (ExecutionException e) {
312 fail(e.getMessage());
316 debuggerSession[0].getProcess().getProcessHandler().addProcessListener(new ProcessAdapter() {
318 public void onTextAvailable(ProcessEvent event, Key outputType) {
319 print(event.getText(), outputType);
322 return debuggerSession[0];
325 protected void createBreakpoints(final String className) {
326 final PsiFile psiFile = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
328 public PsiFile compute() {
329 PsiClass psiClass = JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject));
330 assertNotNull(psiClass);
331 return psiClass.getContainingFile();
335 createBreakpoints(psiFile);
338 protected EvaluationContextImpl createEvaluationContext(final SuspendContextImpl suspendContext) {
340 StackFrameProxyImpl proxy = suspendContext.getFrameProxy();
341 assertNotNull(proxy);
342 return new EvaluationContextImpl(suspendContext, proxy, proxy.thisObject());
344 catch (EvaluateException e) {
350 protected void waitForCompleted() {
351 final SynchronizationBasedSemaphore s = new SynchronizationBasedSemaphore();
354 final InvokeThread.WorkerThreadRequest request = getDebugProcess().getManagerThread().getCurrentRequest();
355 final Thread thread = new Thread("Joining "+request) {
361 catch (Exception ignored) {
366 if(request.isDone()) {
369 waitFor(new Runnable() {
375 catch (InterruptedException ignored) {
380 invokeRatherLater(new DebuggerCommandImpl() {
382 protected void action() throws Exception {
383 LOG.assertTrue(false);
387 protected void commandCancelled() {
388 //We wait for invokeRatherLater's
389 invokeRatherLater(new DebuggerCommandImpl() {
391 protected void action() throws Exception {
392 LOG.assertTrue(false);
396 protected void commandCancelled() {
403 waitFor(new Runnable() {
411 public DebuggerContextImpl createDebuggerContext(final SuspendContextImpl suspendContext, StackFrameProxyImpl stackFrame) {
412 final DebuggerSession[] session = new DebuggerSession[1];
414 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
417 session[0] = DebuggerManagerEx.getInstanceEx(myProject).getSession(suspendContext.getDebugProcess());
421 DebuggerContextImpl debuggerContext = DebuggerContextImpl.createDebuggerContext(
424 stackFrame != null ? stackFrame.threadProxy() : null,
426 debuggerContext.initCaches();
427 return debuggerContext;
430 public DebuggerContextImpl createDebuggerContext(final SuspendContextImpl suspendContext) {
431 return createDebuggerContext(suspendContext, suspendContext.getFrameProxy());
434 protected void printLocation(SuspendContextImpl suspendContext) {
436 Location location = suspendContext.getFrameProxy().location();
437 String message = "paused at " + location.sourceName() + ":" + location.lineNumber();
438 println(message, ProcessOutputTypes.SYSTEM);
440 catch (Throwable e) {
445 protected void createBreakpointInHelloWorld() {
446 DebuggerInvocationUtil.invokeAndWait(myProject, new Runnable() {
449 BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
450 PsiClass psiClass = JavaPsiFacade.getInstance(myProject).findClass("HelloWorld", GlobalSearchScope.allScope(myProject));
451 assertNotNull(psiClass);
452 Document document = PsiDocumentManager.getInstance(myProject).getDocument(psiClass.getContainingFile());
453 breakpointManager.addLineBreakpoint(document, 3);
455 }, ApplicationManager.getApplication().getDefaultModalityState());
458 protected void createHelloWorldProcessWithBreakpoint() throws ExecutionException, InterruptedException, InvocationTargetException {
459 createLocalProcess("HelloWorld");
461 createBreakpointInHelloWorld();
465 protected DebugProcessImpl getDebugProcess() {
466 return myDebuggerSession != null ? myDebuggerSession.getProcess() : null;
469 public DebuggerSession getDebuggerSession() {
470 return myDebuggerSession;
473 protected DebuggerSession attachVirtualMachine(RunProfileState state,
474 ExecutionEnvironment environment,
475 RemoteConnection remoteConnection,
476 boolean pollConnection) throws ExecutionException {
477 final DebuggerSession debuggerSession =
478 DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(new DefaultDebugEnvironment(environment, state, remoteConnection, pollConnection));
479 XDebuggerManager.getInstance(myProject).startSession(environment, new XDebugProcessStarter() {
482 public XDebugProcess start(@NotNull XDebugSession session) {
483 return JavaDebugProcess.create(session, debuggerSession);
486 return debuggerSession;
489 public class MockConfiguration implements ModuleRunConfiguration {
492 public Module[] getModules() {
493 if (myModule != null) {
494 return new Module[]{myModule};
497 return Module.EMPTY_ARRAY;
502 public Icon getIcon() {
507 public ConfigurationFactory getFactory() {
512 public void setName(String name) { }
516 public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
517 throw new UnsupportedOperationException();
521 public Project getProject() {
527 public ConfigurationType getType() {
528 return UnknownConfigurationType.INSTANCE;
532 public ConfigurationPerRunnerSettings createRunnerSettings(ConfigurationInfoProvider provider) {
537 public SettingsEditor<ConfigurationPerRunnerSettings> getRunnerSettingsEditor(ProgramRunner runner) {
542 public RunConfiguration clone() {
547 public int getUniqueID() {
552 public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
557 public String getName() {
562 public void checkConfiguration() throws RuntimeConfigurationException { }
565 public void readExternal(Element element) throws InvalidDataException { }
568 public void writeExternal(Element element) throws WriteExternalException { }