Snapshot aea001abfc1b38fec3a821bcd5174cc77dc75787 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: Icdea2a2bd7ad43b4d05967b1f0479db3bda1c93c
diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
index 6d40070..ccaa2cb 100644
--- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
@@ -119,16 +119,17 @@
@Override
@NotNull
- public InspectionTool[] getInspectionTools(PsiElement element) {
+ public InspectionToolWrapper[] getInspectionTools(PsiElement element) {
Collection<InspectionToolWrapper> values = myAvailableTools.values();
- return values.toArray(new InspectionTool[values.size()]);
+ return values.toArray(new InspectionToolWrapper[values.size()]);
}
+ @NotNull
@Override
- public List<ToolsImpl> getAllEnabledInspectionTools(Project project) {
- List<ToolsImpl> result = new ArrayList<ToolsImpl>();
- for (InspectionProfileEntry entry : getInspectionTools(null)) {
- result.add(new ToolsImpl(entry, entry.getDefaultLevel(), true));
+ public List<Tools> getAllEnabledInspectionTools(Project project) {
+ List<Tools> result = new ArrayList<Tools>();
+ for (InspectionToolWrapper toolWrapper : getInspectionTools(null)) {
+ result.add(new ToolsImpl(toolWrapper, toolWrapper.getDefaultLevel(), true));
}
return result;
}
@@ -140,12 +141,12 @@
@Override
public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, PsiElement element) {
- final InspectionProfileEntry localInspectionTool = myAvailableTools.get(key.toString());
+ final InspectionToolWrapper localInspectionTool = myAvailableTools.get(key.toString());
return localInspectionTool != null ? localInspectionTool.getDefaultLevel() : HighlightDisplayLevel.WARNING;
}
@Override
- public InspectionTool getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) {
+ public InspectionToolWrapper getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) {
return myAvailableTools.get(shortName);
}
};
@@ -192,14 +193,9 @@
//((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).assertPointersDisposed();
}
- protected void enableInspectionTool(InspectionProfileEntry tool){
- InspectionToolWrapper wrapper = InspectionToolRegistrar.wrapTool(tool);
- final String shortName = wrapper.getShortName();
- final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
- if (key == null) {
- HighlightDisplayKey.register(shortName, wrapper.getDisplayName(), ((LocalInspectionToolWrapper)wrapper).getID());
- }
- myAvailableTools.put(shortName, wrapper);
+ protected void enableInspectionTool(@NotNull InspectionProfileEntry tool) {
+ InspectionToolWrapper toolWrapper = InspectionToolRegistrar.wrapTool(tool);
+ LightPlatformTestCase.enableInspectionTool(myAvailableTools, toolWrapper);
}
protected void enableInspectionToolsFromProvider(InspectionToolProvider toolProvider){
diff --git a/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java
new file mode 100644
index 0000000..e1f9857
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger;
+
+import com.intellij.debugger.engine.DebugProcessImpl;
+import com.intellij.debugger.engine.RemoteStateState;
+import com.intellij.debugger.engine.SuspendContextImpl;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.intellij.debugger.engine.events.DebuggerCommandImpl;
+import com.intellij.debugger.impl.*;
+import com.intellij.debugger.jdi.StackFrameProxyImpl;
+import com.intellij.debugger.settings.DebuggerSettings;
+import com.intellij.debugger.settings.NodeRendererSettings;
+import com.intellij.debugger.ui.breakpoints.BreakpointManager;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.configurations.*;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.ui.UIUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.lang.reflect.InvocationTargetException;
+import java.util.StringTokenizer;
+
+public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCase {
+ protected DebuggerSession myDebuggerSession;
+ private StringBuffer myConsoleBuffer;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void initApplication() throws Exception {
+ super.initApplication();
+ setTestJDK();
+ DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = DebuggerSettings.SOCKET_TRANSPORT;
+ DebuggerSettings.getInstance().SKIP_CONSTRUCTORS = false;
+ DebuggerSettings.getInstance().SKIP_GETTERS = false;
+ NodeRendererSettings.getInstance().getClassRenderer().SHOW_DECLARED_TYPE = true;
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ super.runTest();
+ if(getDebugProcess() != null) {
+ getDebugProcess().getExecutionResult().getProcessHandler().startNotify();
+ waitProcess(getDebugProcess().getExecutionResult().getProcessHandler());
+ waitForCompleted();
+ disposeSession(myDebuggerSession);
+ assertNull(DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(getDebugProcess().getExecutionResult().getProcessHandler()));
+ myDebuggerSession = null;
+ }
+ if(myConsoleBuffer != null) {
+ //println("", b);
+ //println("Console output:", b);
+ //println(myConsoleBuffer.toString(), b);
+ }
+ checkTestOutput();
+ }
+
+ protected void checkTestOutput() throws Exception {
+ getChecker().checkValid(getTestProjectJdk());
+ }
+
+ protected void disposeSession(final DebuggerSession debuggerSession) throws InterruptedException, InvocationTargetException {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ debuggerSession.dispose();
+ }
+ });
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ myConsoleBuffer = null;
+ }
+
+ protected void createLocalProcess(String className) throws ExecutionException, InterruptedException, InvocationTargetException {
+ LOG.assertTrue(myDebugProcess == null);
+ myDebuggerSession = createLocalProcess(DebuggerSettings.SOCKET_TRANSPORT, createJavaParameters(className));
+ myDebugProcess = myDebuggerSession.getProcess();
+ }
+
+ protected DebuggerSession createLocalSession(final JavaParameters javaParameters, final String sessionName) throws ExecutionException, InterruptedException {
+ createBreakpoints(javaParameters.getMainClass());
+ DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = DebuggerSettings.SOCKET_TRANSPORT;
+
+ GenericDebuggerRunnerSettings debuggerRunnerSettings = new GenericDebuggerRunnerSettings();
+ debuggerRunnerSettings.LOCAL = true;
+
+ final RemoteConnection debugParameters = DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerRunnerSettings, false);
+
+ RunnerSettings<JDOMExternalizable> runnerSettings = new RunnerSettings<JDOMExternalizable>(debuggerRunnerSettings, null);
+
+ final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(new ExecutionEnvironment(new MockConfiguration(), myProject,
+ runnerSettings, null, null)){
+ @Override
+ protected JavaParameters createJavaParameters() {
+ return javaParameters;
+ }
+
+ @Override
+ protected GeneralCommandLine createCommandLine() throws ExecutionException {
+ return CommandLineBuilder.createFromJavaParameters(getJavaParameters());
+ }
+ };
+
+ final GenericDebuggerRunner runner = new GenericDebuggerRunner();
+
+ ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ myDebuggerSession = DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(new DefaultDebugExecutor(),
+ runner, new MockConfiguration(), javaCommandLineState, debugParameters, false);
+ }
+ catch (ExecutionException e) {
+ LOG.error(e);
+ }
+ }
+ }, ModalityState.defaultModalityState());
+ myDebugProcess = myDebuggerSession.getProcess();
+
+ //myConsoleBuffer = new StringBuffer();
+
+ myDebugProcess.addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ //myConsoleBuffer.append(event.getText());
+ print(event.getText(), outputType);
+ }
+ });
+
+ assertNotNull(myDebuggerSession);
+ assertNotNull(myDebugProcess);
+
+ return myDebuggerSession;
+ }
+
+
+ protected DebuggerSession createLocalProcess(int transport, final JavaParameters javaParameters) throws ExecutionException, InterruptedException, InvocationTargetException {
+ createBreakpoints(javaParameters.getMainClass());
+ final DebuggerSession[] debuggerSession = new DebuggerSession[]{null};
+
+ DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = transport;
+
+ GenericDebuggerRunnerSettings debuggerRunnerSettings = new GenericDebuggerRunnerSettings();
+ debuggerRunnerSettings.LOCAL = true;
+ debuggerRunnerSettings.DEBUG_PORT = "3456";
+
+ RunnerSettings<JDOMExternalizable> runnerSettings = new RunnerSettings<JDOMExternalizable>(debuggerRunnerSettings, null);
+
+ final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(new ExecutionEnvironment(new MockConfiguration(), myProject,
+ runnerSettings, null, null)) {
+ @Override
+ protected JavaParameters createJavaParameters() {
+ return javaParameters;
+ }
+
+ @Override
+ protected GeneralCommandLine createCommandLine() throws ExecutionException {
+ return CommandLineBuilder.createFromJavaParameters(getJavaParameters());
+ }
+ };
+
+ final RemoteConnection debugParameters =
+ DebuggerManagerImpl.createDebugParameters(javaCommandLineState.getJavaParameters(), debuggerRunnerSettings, true);
+
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ debuggerSession[0] = attachVirtualMachine(javaCommandLineState, debugParameters, false);
+ }
+ catch (ExecutionException e) {
+ fail(e.getMessage());
+ }
+ }
+ });
+
+ final ExecutionResult executionResult = debuggerSession[0].getProcess().getExecutionResult();
+ debuggerSession[0].getProcess().addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ print(event.getText(), outputType);
+ }
+ });
+
+ DebugProcessImpl process =
+ (DebugProcessImpl)DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(executionResult.getProcessHandler());
+ assertNotNull(process);
+ return debuggerSession[0];
+ }
+
+
+ protected DebuggerSession createRemoteProcess(final int transport, final boolean serverMode, JavaParameters javaParameters)
+ throws ExecutionException, InterruptedException, InvocationTargetException {
+ boolean useSockets = transport == DebuggerSettings.SOCKET_TRANSPORT;
+
+ RemoteConnection remoteConnection = new RemoteConnection(
+ useSockets,
+ "127.0.0.1",
+ "3456",
+ serverMode);
+
+ String launchCommandLine = remoteConnection.getLaunchCommandLine();
+
+ launchCommandLine = StringUtil.replace(launchCommandLine, RemoteConnection.ONTHROW, "");
+ launchCommandLine = StringUtil.replace(launchCommandLine, RemoteConnection.ONUNCAUGHT, "");
+
+ launchCommandLine = StringUtil.replace(launchCommandLine, "suspend=n", "suspend=y");
+
+ println(launchCommandLine, ProcessOutputTypes.SYSTEM);
+
+ JavaParameters parameters = javaParameters;
+
+ for(StringTokenizer tokenizer = new StringTokenizer(launchCommandLine);tokenizer.hasMoreTokens();) {
+ String token = tokenizer.nextToken();
+ parameters.getVMParametersList().add(token);
+ }
+
+ GeneralCommandLine commandLine = CommandLineBuilder.createFromJavaParameters(parameters);
+
+
+ DebuggerSession debuggerSession;
+
+ if(serverMode) {
+ debuggerSession = attachVM(remoteConnection, false);
+ commandLine.createProcess();
+ } else {
+ commandLine.createProcess();
+ debuggerSession = attachVM(remoteConnection, true);
+ }
+
+ ExecutionResult executionResult = debuggerSession.getProcess().getExecutionResult();
+ DebugProcessImpl process = (DebugProcessImpl)DebuggerManagerEx.getInstanceEx(myProject)
+ .getDebugProcess(executionResult.getProcessHandler());
+
+ assertNotNull(process);
+ return debuggerSession;
+ }
+
+ protected DebuggerSession attachVM(final RemoteConnection remoteConnection, final boolean pollConnection)
+ throws InvocationTargetException, InterruptedException {
+ final RunnerSettings<JDOMExternalizable> runnerSettings = new RunnerSettings<JDOMExternalizable>(null, null);
+ final RemoteState remoteState = new RemoteStateState(myProject, remoteConnection, runnerSettings, null);
+
+ final DebuggerSession[] debuggerSession = new DebuggerSession[1];
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ debuggerSession[0] = attachVirtualMachine(remoteState, remoteConnection, pollConnection);
+ }
+ catch (ExecutionException e) {
+ fail(e.getMessage());
+ }
+ }
+ });
+ debuggerSession[0].getProcess().getExecutionResult().getProcessHandler().addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ print(event.getText(), outputType);
+ }
+ });
+ return debuggerSession[0];
+ }
+
+ protected void createBreakpoints(final String className) {
+ final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
+ @Override
+ public PsiClass compute() {
+ return JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject));
+ }
+ });
+
+ createBreakpoints(psiClass.getContainingFile());
+
+ }
+
+ protected EvaluationContextImpl createEvaluationContext(final SuspendContextImpl suspendContext) {
+ try {
+ return new EvaluationContextImpl(
+ suspendContext,
+ suspendContext.getFrameProxy(),
+ suspendContext.getFrameProxy().thisObject());
+ }
+ catch (EvaluateException e) {
+ error(e);
+ return null;
+ }
+ }
+
+ protected void waitForCompleted() {
+ final SynchronizationBasedSemaphore s = new SynchronizationBasedSemaphore();
+ s.down();
+
+ final InvokeThread.WorkerThreadRequest request = getDebugProcess().getManagerThread().getCurrentRequest();
+ final Thread thread = new Thread("Joining "+request) {
+ @Override
+ public void run() {
+ try {
+ request.join();
+ }
+ catch (Exception e) {
+ }
+ }
+ };
+ thread.start();
+ if(request.isDone()) {
+ thread.interrupt();
+ }
+ waitFor(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ thread.join();
+ }
+ catch (InterruptedException e) {
+ }
+ }
+ });
+
+ invokeRatherLater(new DebuggerCommandImpl() {
+ @Override
+ protected void action() throws Exception {
+ LOG.assertTrue(false);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ //We wait for invokeRatherLater's
+ invokeRatherLater(new DebuggerCommandImpl() {
+ @Override
+ protected void action() throws Exception {
+ LOG.assertTrue(false);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ s.up();
+ }
+ });
+ }
+ });
+
+ waitFor(new Runnable() {
+ @Override
+ public void run() {
+ s.waitFor();
+ }
+ });
+ }
+
+ public DebuggerContextImpl createDebuggerContext(final SuspendContextImpl suspendContext, StackFrameProxyImpl stackFrame) {
+ final DebuggerSession[] session = new DebuggerSession[1];
+
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ session[0] = DebuggerManagerEx.getInstanceEx(myProject).getSession(suspendContext.getDebugProcess());
+ }
+ });
+
+ DebuggerContextImpl debuggerContext = DebuggerContextImpl.createDebuggerContext(
+ session[0],
+ suspendContext,
+ stackFrame != null ? stackFrame.threadProxy() : null,
+ stackFrame);
+ debuggerContext.initCaches();
+ return debuggerContext;
+ }
+
+ public DebuggerContextImpl createDebuggerContext(final SuspendContextImpl suspendContext) {
+ return createDebuggerContext(suspendContext, suspendContext.getFrameProxy());
+ }
+
+ protected void createBreakpointInHelloWorld() {
+ DebuggerInvocationUtil.invokeAndWait(myProject, new Runnable() {
+ @Override
+ public void run() {
+ BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager();
+ PsiClass psiClass = JavaPsiFacade.getInstance(myProject).findClass("HelloWorld", GlobalSearchScope.allScope(myProject));
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(psiClass.getContainingFile());
+ breakpointManager.addLineBreakpoint(document, 3);
+ }
+ }, ApplicationManager.getApplication().getDefaultModalityState());
+ }
+
+ protected void createHelloWorldProcessWithBreakpoint() throws ExecutionException, InterruptedException, InvocationTargetException {
+ createLocalProcess("HelloWorld");
+
+ createBreakpointInHelloWorld();
+ }
+
+ @Override
+ protected DebugProcessImpl getDebugProcess() {
+ return myDebuggerSession != null ? myDebuggerSession.getProcess() : null;
+ }
+
+ public DebuggerSession getDebuggerSession() {
+ return myDebuggerSession;
+ }
+
+ protected DebuggerSession attachVirtualMachine(RunProfileState state, RemoteConnection remoteConnection, boolean pollConnection) throws ExecutionException {
+ return DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(new DefaultDebugExecutor(), new GenericDebuggerRunner(), new MockConfiguration(), state, remoteConnection, pollConnection);
+ }
+
+ private static class MockConfiguration implements ModuleRunConfiguration {
+ @Override
+ @NotNull
+ public Module[] getModules() {
+ return Module.EMPTY_ARRAY; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Icon getIcon() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public ConfigurationFactory getFactory() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void setName(final String name) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public Project getProject() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ @NotNull
+ public ConfigurationType getType() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public JDOMExternalizable createRunnerSettings(final ConfigurationInfoProvider provider) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public SettingsEditor<JDOMExternalizable> getRunnerSettingsEditor(final ProgramRunner runner) {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public RunConfiguration clone() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public int getUniqueID() {
+ return 0;
+ }
+
+ @Override
+ public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public String getName() {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void checkConfiguration() throws RuntimeConfigurationException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void readExternal(final Element element) throws InvalidDataException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public void writeExternal(final Element element) throws WriteExternalException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+ }
+
+}
diff --git a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
new file mode 100644
index 0000000..bccbfe5
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger;
+
+import com.intellij.debugger.engine.*;
+import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
+import com.intellij.debugger.engine.events.DebuggerCommandImpl;
+import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
+import com.intellij.debugger.impl.DebuggerManagerImpl;
+import com.intellij.debugger.impl.PositionUtil;
+import com.intellij.debugger.impl.PrioritizedTask;
+import com.intellij.debugger.impl.SynchronizationBasedSemaphore;
+import com.intellij.debugger.jdi.StackFrameProxyImpl;
+import com.intellij.debugger.settings.DebuggerSettings;
+import com.intellij.debugger.ui.breakpoints.Breakpoint;
+import com.intellij.debugger.ui.breakpoints.BreakpointManager;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionTestCase;
+import com.intellij.execution.configurations.RemoteConnection;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.projectRoots.ProjectJdkTable;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.ui.classFilter.ClassFilter;
+import com.intellij.util.IJSwingUtilities;
+import com.intellij.util.ui.UIUtil;
+import com.sun.jdi.Method;
+import com.sun.jdi.ThreadReference;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCase {
+ private DebugProcessListener myPauseScriptListener = null;
+ private final List<SuspendContextRunnable> myScriptRunnables = new ArrayList<SuspendContextRunnable>();
+ private final SynchronizationBasedSemaphore myScriptRunnablesSema = new SynchronizationBasedSemaphore();
+ protected static final int RATHER_LATER_INVOKES_N = 10;
+ public DebugProcessImpl myDebugProcess = null;
+
+
+ private class InvokeRatherLaterRequest {
+ private final DebuggerCommandImpl myDebuggerCommand;
+ private final DebugProcessImpl myDebugProcess;
+ int invokesN = 0;
+
+ public InvokeRatherLaterRequest(DebuggerCommandImpl debuggerCommand, DebugProcessImpl debugProcess) {
+ myDebuggerCommand = debuggerCommand;
+ myDebugProcess = debugProcess;
+ }
+ }
+
+ public List<InvokeRatherLaterRequest> myRatherLaterRequests = new ArrayList<InvokeRatherLaterRequest>();
+
+ protected DebugProcessImpl getDebugProcess() {
+ return myDebugProcess;
+ }
+
+ protected String readValue(String comment, String valueName) {
+ int valueStart = comment.indexOf(valueName);
+ if (valueStart == -1) return null;
+
+ int valueEnd = comment.indexOf(')', valueStart);
+ return comment.substring(valueStart + valueName.length() + 1, valueEnd);
+ }
+
+ protected void resume(SuspendContextImpl context) {
+ DebugProcessImpl debugProcess = context.getDebugProcess();
+ debugProcess.getManagerThread().schedule(debugProcess.createResumeCommand(context, PrioritizedTask.Priority.LOW));
+ }
+
+ protected void waitBreakpoints() {
+ myScriptRunnablesSema.down();
+ waitFor(new Runnable() {
+ @Override
+ public void run() {
+ myScriptRunnablesSema.waitFor();
+ }
+ });
+ }
+
+ protected void onBreakpoint(SuspendContextRunnable runnable) {
+ if (myPauseScriptListener == null) {
+ final DebugProcessImpl debugProcess = getDebugProcess();
+
+ assertTrue("Debug process was not started", debugProcess != null);
+
+ myPauseScriptListener = new DelayedEventsProcessListener(
+ new DebugProcessAdapterImpl() {
+ @Override
+ public void paused(SuspendContextImpl suspendContext) {
+ try {
+ if (myScriptRunnables.isEmpty()) {
+ print("resuming ", ProcessOutputTypes.SYSTEM);
+ printContext(suspendContext);
+ resume(suspendContext);
+ return;
+ }
+ SuspendContextRunnable suspendContextRunnable = myScriptRunnables.remove(0);
+ suspendContextRunnable.run(suspendContext);
+ }
+ catch (Exception e) {
+ error(e);
+ }
+
+ if (myScriptRunnables.isEmpty()) {
+ myScriptRunnablesSema.up();
+ }
+ }
+
+ //executed in manager thread
+ @Override
+ public void resumed(SuspendContextImpl suspendContext) {
+ final SuspendContextImpl pausedContext = debugProcess.getSuspendManager().getPausedContext();
+ if (pausedContext != null) {
+ debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(pausedContext) {
+ @Override
+ public void contextAction() throws Exception {
+ paused(pausedContext);
+ }
+ });
+ }
+ }
+ }
+ );
+ debugProcess.addDebugProcessListener(myPauseScriptListener);
+ }
+ myScriptRunnables.add(runnable);
+ }
+
+ protected void printFrameProxy(StackFrameProxyImpl frameProxy) throws EvaluateException {
+ int frameIndex = frameProxy.getFrameIndex();
+ Method method = frameProxy.location().method();
+
+ println("frameProxy(" + frameIndex + ") = " + method, ProcessOutputTypes.SYSTEM);
+ }
+
+ protected void printContext(final StackFrameContext context) {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ if (context.getFrameProxy() != null) {
+ SourcePosition sourcePosition = PositionUtil.getSourcePosition(context);
+ println(sourcePosition.getFile().getVirtualFile().getName() + ":" + sourcePosition.getLine(), ProcessOutputTypes.SYSTEM);
+ }
+ else {
+ println("Context thread is null", ProcessOutputTypes.SYSTEM);
+ }
+ }
+ });
+ }
+
+ protected void invokeRatherLater(SuspendContextImpl context, final Runnable runnable) {
+ invokeRatherLater(new SuspendContextCommandImpl(context) {
+ @Override
+ public void contextAction() throws Exception {
+ DebuggerInvocationUtil.invokeLater(myProject, runnable);
+ }
+ });
+ }
+
+ protected void pumpSwingThread() {
+ LOG.assertTrue(SwingUtilities.isEventDispatchThread());
+
+ final InvokeRatherLaterRequest request = myRatherLaterRequests.get(0);
+ request.invokesN++;
+
+ if (request.invokesN == RATHER_LATER_INVOKES_N) {
+ myRatherLaterRequests.remove(0);
+ if (!myRatherLaterRequests.isEmpty()) pumpSwingThread();
+ }
+
+ if (request.myDebuggerCommand instanceof SuspendContextCommandImpl) {
+ request.myDebugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(
+ ((SuspendContextCommandImpl)request.myDebuggerCommand).getSuspendContext()) {
+ @Override
+ public void contextAction() throws Exception {
+ pumpDebuggerThread(request);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ pumpDebuggerThread(request);
+ }
+ });
+ }
+ else {
+ request.myDebugProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
+ @Override
+ protected void action() throws Exception {
+ pumpDebuggerThread(request);
+ }
+
+ @Override
+ protected void commandCancelled() {
+ pumpDebuggerThread(request);
+ }
+ });
+ }
+ }
+
+ private void pumpDebuggerThread(final InvokeRatherLaterRequest request) {
+ if (request.invokesN == RATHER_LATER_INVOKES_N) {
+ request.myDebugProcess.getManagerThread().schedule(request.myDebuggerCommand);
+ }
+ else {
+ if (!SwingUtilities.isEventDispatchThread()) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ pumpSwingThread();
+ }
+ });
+ }
+ else {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ pumpSwingThread();
+ }
+ });
+ }
+ }
+ }
+
+ protected void invokeRatherLater(final DebuggerCommandImpl command) {
+ IJSwingUtilities.invoke(new Runnable() {
+ @Override
+ public void run() {
+ InvokeRatherLaterRequest request = new InvokeRatherLaterRequest(command, getDebugProcess());
+ myRatherLaterRequests.add(request);
+
+ if (myRatherLaterRequests.size() == 1) pumpSwingThread();
+ }
+ });
+ }
+
+
+ protected void error(Throwable th) {
+ fail(StringUtil.getThrowableText(th));
+ }
+
+ public void createBreakpoints(final PsiFile file) {
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ BreakpointManager breakpointManager = DebuggerManagerImpl.getInstanceEx(myProject).getBreakpointManager();
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
+ int offset = -1;
+ for (; ;) {
+ offset = document.getText().indexOf("Breakpoint!", offset + 1);
+ if (offset == -1) break;
+
+ int commentLine = document.getLineNumber(offset);
+
+ String comment = document.getText().substring(document.getLineStartOffset(commentLine), document.getLineEndOffset(commentLine));
+
+ Breakpoint breakpoint;
+
+ if (comment.indexOf("Method") != -1) {
+ breakpoint = breakpointManager.addMethodBreakpoint(document, commentLine + 1);
+ println("MethodBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+ else if (comment.indexOf("Field") != -1) {
+ breakpoint = breakpointManager.addFieldBreakpoint(document, commentLine + 1, readValue(comment, "Field"));
+ println("FieldBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+ else if (comment.indexOf("Exception") != -1) {
+ breakpoint = breakpointManager.addExceptionBreakpoint(readValue(comment, "Exception"), "");
+ println("ExceptionBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+ else {
+ breakpoint = breakpointManager.addLineBreakpoint(document, commentLine + 1);
+ println("LineBreakpoint created at " + file.getVirtualFile().getName() + ":" + (commentLine + 2), ProcessOutputTypes.SYSTEM);
+ }
+
+ String suspendPolicy = readValue(comment, "suspendPolicy");
+ if (suspendPolicy != null) {
+ breakpoint.SUSPEND = !DebuggerSettings.SUSPEND_NONE.equals(suspendPolicy);
+ breakpoint.SUSPEND_POLICY = suspendPolicy;
+ println("SUSPEND_POLICY = " + suspendPolicy, ProcessOutputTypes.SYSTEM);
+ }
+ String condition = readValue(comment, "Condition");
+ if (condition != null) {
+ breakpoint.CONDITION_ENABLED = true;
+ breakpoint.setCondition(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, condition));
+ println("Condition = " + condition, ProcessOutputTypes.SYSTEM);
+ }
+ String passCount = readValue(comment, "Pass count");
+ if (passCount != null) {
+ breakpoint.COUNT_FILTER_ENABLED = true;
+ breakpoint.COUNT_FILTER = Integer.parseInt(passCount);
+ println("Pass count = " + passCount, ProcessOutputTypes.SYSTEM);
+ }
+
+ String classFilters = readValue(comment, "Class filters");
+ if (classFilters != null) {
+ breakpoint.CLASS_FILTERS_ENABLED = true;
+ StringTokenizer tokenizer = new StringTokenizer(classFilters, " ,");
+ ArrayList<ClassFilter> lst = new ArrayList<ClassFilter>();
+
+ while (tokenizer.hasMoreTokens()) {
+ ClassFilter filter = new ClassFilter();
+ filter.setEnabled(true);
+ filter.setPattern(tokenizer.nextToken());
+ lst.add(filter);
+ }
+
+ breakpoint.setClassFilters(lst.toArray(new ClassFilter[lst.size()]));
+ println("Class filters = " + classFilters, ProcessOutputTypes.SYSTEM);
+ }
+ }
+ }
+ };
+ if (!SwingUtilities.isEventDispatchThread()) {
+ DebuggerInvocationUtil.invokeAndWait(myProject, runnable, ModalityState.defaultModalityState());
+ }
+ else {
+ runnable.run();
+ }
+ }
+
+ private Sdk getTestJdk() {
+ try {
+ ProjectJdkImpl jdk = (ProjectJdkImpl)JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk().clone();
+ jdk.setName("JDK");
+ return jdk;
+ }
+ catch (CloneNotSupportedException e) {
+ LOG.error(e);
+ return null;
+ }
+ }
+
+ protected void setTestJDK() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ Sdk jdk = ProjectJdkTable.getInstance().findJdk("JDK");
+ if (jdk != null) {
+ ProjectJdkTable.getInstance().removeJdk(jdk);
+ }
+
+ ProjectJdkTable.getInstance().addJdk(getTestJdk());
+ }
+ });
+ }
+
+ private class DelayedEventsProcessListener implements DebugProcessListener {
+ private final DebugProcessAdapterImpl myTarget;
+
+ public DelayedEventsProcessListener(DebugProcessAdapterImpl target) {
+ myTarget = target;
+ }
+
+ @Override
+ public void threadStarted(DebugProcess proc, ThreadReference thread) {
+ }
+
+ @Override
+ public void threadStopped(DebugProcess proc, ThreadReference thread) {
+ }
+
+ @Override
+ public void paused(final SuspendContext suspendContext) {
+ pauseExecution();
+ myTarget.paused(suspendContext);
+ }
+
+ @Override
+ public void resumed(final SuspendContext suspendContext) {
+ pauseExecution();
+ myTarget.resumed(suspendContext);
+ }
+
+ @Override
+ public void processDetached(final DebugProcess process, final boolean closedByUser) {
+ myTarget.processDetached(process, closedByUser);
+ }
+
+ @Override
+ public void processAttached(final DebugProcess process) {
+ myTarget.processAttached(process);
+ }
+
+ @Override
+ public void connectorIsReady() {
+ myTarget.connectorIsReady();
+ }
+
+ @Override
+ public void attachException(final RunProfileState state, final ExecutionException exception, final RemoteConnection remoteConnection) {
+ myTarget.attachException(state, exception, remoteConnection);
+ }
+
+ private void pauseExecution() {
+ try {
+ Thread.sleep(10);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
new file mode 100644
index 0000000..0d6624d
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.impl;
+
+import com.intellij.debugger.DebuggerTestCase;
+import com.intellij.debugger.engine.DebugProcessImpl;
+import com.intellij.debugger.engine.SuspendContextImpl;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
+import com.intellij.debugger.engine.jdi.StackFrameProxy;
+import com.intellij.debugger.settings.NodeRendererSettings;
+import com.intellij.debugger.ui.impl.watch.DebuggerTree;
+import com.intellij.debugger.ui.impl.watch.LocalVariableDescriptorImpl;
+import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
+import com.intellij.debugger.ui.tree.DebuggerTreeNode;
+import com.intellij.debugger.ui.tree.NodeDescriptor;
+import com.intellij.debugger.ui.tree.ValueDescriptor;
+import com.intellij.debugger.ui.tree.render.NodeRenderer;
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.openapi.util.Pair;
+import com.sun.jdi.Value;
+
+import java.util.*;
+
+public abstract class DescriptorTestCase extends DebuggerTestCase {
+ private final List<Pair<NodeDescriptorImpl,List<String>>> myDescriptorLog = new ArrayList<Pair<NodeDescriptorImpl, List<String>>>();
+
+ public DescriptorTestCase() {
+ super();
+ }
+
+ protected NodeRenderer getToStringRenderer() {
+ return NodeRendererSettings.getInstance().getToStringRenderer();
+ }
+
+ protected NodeRenderer getMapRenderer() {
+ return getAlternateCollectionRenderer("Map");
+ }
+
+ private NodeRenderer getAlternateCollectionRenderer(final String name) {
+ final NodeRenderer[] renderers = NodeRendererSettings.getInstance().getAlternateCollectionRenderers();
+ for (int idx = 0; idx < renderers.length; idx++) {
+ NodeRenderer renderer = renderers[idx];
+ if (name.equals(renderer.getName())) {
+ return renderer;
+ }
+ }
+ return null;
+ }
+
+ protected NodeRenderer getMapEntryRenderer() {
+ return getAlternateCollectionRenderer("Map.Entry");
+ }
+
+ protected NodeRenderer getHexRenderer() {
+ return NodeRendererSettings.getInstance().getHexRenderer();
+ }
+
+ protected NodeRenderer getCollectionRenderer() {
+ return getAlternateCollectionRenderer("Collection");
+ }
+
+ @Override
+ protected void resume(final SuspendContextImpl suspendContext) {
+ final DebugProcessImpl localProcess = suspendContext.getDebugProcess();
+ invokeRatherLater(new SuspendContextCommandImpl(suspendContext) {
+ @Override
+ public void contextAction() throws Exception {
+ flushDescriptors();
+ localProcess.getManagerThread().schedule(localProcess.createResumeCommand(suspendContext, Priority.LOW));
+ }
+ });
+ }
+
+ protected void logDescriptor(final NodeDescriptorImpl descriptor, String text) {
+ Pair<NodeDescriptorImpl, List<String>> descriptorText = findDescriptorLog(descriptor);
+
+ if(descriptorText == null) {
+ ArrayList<String> allText = new ArrayList<String>();
+ allText.add(text);
+ descriptorText = new Pair<NodeDescriptorImpl, List<String>>(descriptor, allText);
+ myDescriptorLog.add(descriptorText);
+ }
+ else {
+ List<String> allText = descriptorText.getSecond();
+ if(!allText.get(allText.size() - 1).equals(text)) {
+ allText.add(text);
+ }
+ }
+ }
+
+ private Pair<NodeDescriptorImpl, List<String>> findDescriptorLog(final NodeDescriptorImpl descriptor) {
+ Pair<NodeDescriptorImpl, List<String>> descriptorText = null;
+ for (Iterator<Pair<NodeDescriptorImpl, List<String>>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) {
+ Pair<NodeDescriptorImpl, List<String>> pair = iterator.next();
+ if(pair.getFirst() == descriptor) {
+ descriptorText = pair;
+ break;
+ }
+ }
+ return descriptorText;
+ }
+
+ protected void flushDescriptor(final NodeDescriptorImpl descriptor) {
+ Pair<NodeDescriptorImpl, List<String>> descriptorLog = findDescriptorLog(descriptor);
+ if(descriptorLog != null) {
+ printDescriptorLog(descriptorLog);
+ myDescriptorLog.remove(descriptorLog);
+ }
+ }
+
+ protected void flushDescriptors() {
+ for (Iterator<Pair<NodeDescriptorImpl, List<String>>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) {
+ printDescriptorLog(iterator.next());
+ }
+ myDescriptorLog.clear();
+ }
+
+ private void printDescriptorLog(Pair<NodeDescriptorImpl, List<String>> pair) {
+ for (Iterator<String> it = pair.getSecond().iterator(); it.hasNext();) {
+ String text = it.next();
+ print(text, ProcessOutputTypes.SYSTEM);
+ }
+ }
+
+ protected void disableRenderer(NodeRenderer renderer) {
+ renderer.setEnabled(false);
+ }
+
+ protected void enableRenderer(NodeRenderer renderer) {
+ renderer.setEnabled(true);
+ }
+
+ protected LocalVariableDescriptorImpl localVar(DebuggerTree frameTree,
+ EvaluationContextImpl evaluationContext,
+ String name) {
+ try {
+ StackFrameProxy frameProxy = evaluationContext.getFrameProxy();
+ LocalVariableDescriptorImpl local = frameTree.getNodeFactory().getLocalVariableDescriptor(null, frameProxy.visibleVariableByName(name));
+ local.setContext(evaluationContext);
+ return local;
+ } catch (EvaluateException e) {
+ error(e);
+ return null;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ flushDescriptors();
+ super.tearDown();
+ }
+
+ protected void expandAll(final DebuggerTree tree, final Runnable runnable) {
+ doExpandAll(tree, runnable, new HashSet<Value>(), null);
+ }
+
+ protected static interface NodeFilter {
+ boolean shouldExpand(DebuggerTreeNode node);
+ }
+
+ protected void expandAll(final DebuggerTree tree, final Runnable runnable, NodeFilter filter) {
+ doExpandAll(tree, runnable, new HashSet<Value>(), filter);
+ }
+
+ private void doExpandAll(final DebuggerTree tree, final Runnable runnable, final Set<Value> alreadyExpanded, final NodeFilter filter) {
+ invokeRatherLater(tree.getDebuggerContext().getSuspendContext(), new Runnable() {
+ @Override
+ public void run() {
+ boolean anyCollapsed = false;
+ for(int i = 0; i < tree.getRowCount(); i++) {
+ final DebuggerTreeNode treeNode = (DebuggerTreeNode)tree.getPathForRow(i).getLastPathComponent();
+ if(tree.isCollapsed(i) && !treeNode.isLeaf()) {
+ final NodeDescriptor nodeDescriptor = treeNode.getDescriptor();
+ boolean shouldExpand = filter == null? true : filter.shouldExpand(treeNode);
+ if (shouldExpand) {
+ // additional checks to prevent infinite expand
+ if (nodeDescriptor instanceof ValueDescriptor) {
+ final Value value = ((ValueDescriptor)nodeDescriptor).getValue();
+ shouldExpand = !alreadyExpanded.contains(value);
+ if (shouldExpand) {
+ alreadyExpanded.add(value);
+ }
+ }
+ }
+ if (shouldExpand) {
+ anyCollapsed = true;
+ tree.expandRow(i);
+ }
+ }
+ }
+
+ if (anyCollapsed) {
+ doExpandAll(tree, runnable, alreadyExpanded, filter);
+ }
+ else {
+ runnable.run();
+ }
+ }
+ });
+ }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java b/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java
new file mode 100644
index 0000000..9c48ade
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.impl;
+
+import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.idea.IdeaLogger;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.HashMap;
+import junit.framework.Assert;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class OutputChecker {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.OutputChecker");
+
+ protected final String myAppPath;
+
+ public static final Key[] OUTPUT_ORDER = new Key[] {
+ ProcessOutputTypes.SYSTEM, ProcessOutputTypes.STDOUT, ProcessOutputTypes.STDERR
+ };
+ private Map<Key, StringBuffer> myBuffers;
+ protected String myTestName;
+
+
+ //ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2
+ private static final Pattern JDI_BUG_OUTPUT_PATTERN_1 =
+ Pattern.compile("ERROR\\:\\s+JDWP\\s+Unable\\s+to\\s+get\\s+JNI\\s+1\\.2\\s+environment,\\s+jvm-\\>GetEnv\\(\\)\\s+return\\s+code\\s+=\\s+-2\n");
+ //JDWP exit error AGENT_ERROR_NO_JNI_ENV(183): [../../../src/share/back/util.c:820]
+ private static final Pattern JDI_BUG_OUTPUT_PATTERN_2 =
+ Pattern.compile("JDWP\\s+exit\\s+error\\s+AGENT_ERROR_NO_JNI_ENV.*\\]\n");
+
+ public OutputChecker(String appPath) {
+ myAppPath = appPath;
+ }
+
+ public void init(String testName) {
+ IdeaLogger.ourErrorsOccurred = null;
+
+ testName = Character.toLowerCase(testName.charAt(0)) + testName.substring(1);
+ myTestName = testName;
+ synchronized (this) {
+ myBuffers = new HashMap<Key, StringBuffer>();
+ }
+ }
+
+ public void print(String s, Key outputType) {
+ synchronized (this) {
+ if (myBuffers != null) {
+ StringBuffer buffer = myBuffers.get(outputType);
+ if (buffer == null) {
+ myBuffers.put(outputType, buffer = new StringBuffer());
+ }
+ buffer.append(s);
+ }
+ }
+ }
+
+ public void println(String s, Key outputType) {
+ print(s + "\n", outputType);
+ }
+
+ public void checkValid(Sdk jdk) throws Exception {
+ checkValid(jdk, false);
+ }
+
+ public void checkValid(Sdk jdk, boolean sortClassPath) throws Exception {
+ if (IdeaLogger.ourErrorsOccurred != null) {
+ throw IdeaLogger.ourErrorsOccurred;
+ }
+
+ String actual = preprocessBuffer(jdk, buildOutputString(), sortClassPath);
+
+ File outs = new File(myAppPath + File.separator + "outs");
+ assert outs.exists() || outs.mkdirs() : outs;
+
+ File outFile = new File(outs, myTestName + ".out");
+ if (!outFile.exists()) {
+ if (SystemInfo.isWindows) {
+ final File winOut = new File(outs, myTestName + ".win.out");
+ if (winOut.exists()) {
+ outFile = winOut;
+ }
+ }
+ else if (SystemInfo.isUnix) {
+ final File unixOut = new File(outs, myTestName + ".unx.out");
+ if (unixOut.exists()) {
+ outFile = unixOut;
+ }
+ }
+ }
+
+ if (!outFile.exists()) {
+ FileOutputStream fos = new FileOutputStream(outFile, false);
+ try {
+ fos.write(actual.getBytes());
+ }
+ finally {
+ fos.close();
+ }
+ LOG.error("Test file created " + outFile.getPath() + "\n" + "**************** Don't forget to put it into VCS! *******************");
+ }
+ else {
+ String originalText = FileUtil.loadFile(outFile);
+ String expected = originalText;
+
+ expected = StringUtil.replace(expected, "\r\n", "\n");
+ expected = StringUtil.replace(expected, "\r", "\n");
+
+ if (!expected.equals(actual)) {
+ System.out.println("expected:");
+ System.out.println(originalText);
+ System.out.println("actual:");
+ System.out.println(actual);
+
+ Assert.assertEquals(originalText, actual);
+ }
+ }
+ }
+
+ private synchronized String buildOutputString() {
+ final StringBuilder result = new StringBuilder();
+ for (Key key : OUTPUT_ORDER) {
+ final StringBuffer buffer = myBuffers.get(key);
+ if (buffer != null) {
+ result.append(buffer.toString());
+ }
+ }
+ return result.toString();
+ }
+
+ private String preprocessBuffer(final Sdk testJdk, final String buffer, final boolean sortClassPath) throws Exception {
+ Application application = ApplicationManager.getApplication();
+
+ if (application == null) return buffer;
+
+ final Exception[] ex = new Exception[]{null};
+
+ String actual = application.runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ try {
+ String internalJdkHome = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk().getHomeDirectory().getPath();
+ //System.out.println("internalJdkHome = " + internalJdkHome);
+
+ String result = buffer;
+ //System.out.println("Original Output = " + result);
+ final boolean shouldIgnoreCase = !SystemInfo.isFileSystemCaseSensitive;
+
+ result = StringUtil.replace(result, "\r\n", "\n");
+ result = StringUtil.replace(result, "\r", "\n");
+ result = StringUtil.replace(result, testJdk.getHomePath(), "!TEST_JDK!", shouldIgnoreCase);
+ result = StringUtil.replace(result, myAppPath, "!APP_PATH!", shouldIgnoreCase);
+ result = StringUtil.replace(result, myAppPath.replace(File.separatorChar, '/'), "!APP_PATH!", shouldIgnoreCase);
+ result = StringUtil.replace(result, JavaSdkUtil.getIdeaRtJarPath(), "!RT_JAR!", shouldIgnoreCase);
+ result = StringUtil.replace(result, JavaSdkUtil.getJunit4JarPath(), "!JUNIT4_JAR!", shouldIgnoreCase);
+ result = StringUtil.replace(result, InetAddress.getLocalHost().getCanonicalHostName(), "!HOST_NAME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, InetAddress.getLocalHost().getHostName(), "!HOST_NAME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, "127.0.0.1", "!HOST_NAME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, JavaSdkUtil.getIdeaRtJarPath().replace('/', File.separatorChar), "!RT_JAR!", shouldIgnoreCase);
+ result = StringUtil.replace(result, internalJdkHome.replace('/', File.separatorChar), "!JDK_HOME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, internalJdkHome, "!JDK_HOME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, PathManager.getHomePath(), "!IDEA_HOME!", shouldIgnoreCase);
+ result = StringUtil.replace(result, "Process finished with exit code 255", "Process finished with exit code -1");
+
+ result = replaceAdditionalInOutput(result);
+
+// result = result.replaceAll(" +\n", "\n");
+ result = result.replaceAll("!HOST_NAME!:\\d*", "!HOST_NAME!:!HOST_PORT!");
+ result = result.replaceAll("at \\'.*?\\'", "at '!HOST_NAME!:PORT_NAME!'");
+ result = result.replaceAll("address: \\'.*?\\'", "address: '!HOST_NAME!:PORT_NAME!'");
+ result = result.replaceAll("file.*AppletPage.*\\.html", "file:/!APPLET_HTML!");
+ result = result.replaceAll("\"(!JDK_HOME!.*?)\"", "$1");
+ result = result.replaceAll("\"(!APP_PATH!.*?)\"", "$1");
+
+ result = result.replaceAll("-Didea.launcher.port=\\d*", "-Didea.launcher.port=!IDEA_LAUNCHER_PORT!");
+ result = result.replaceAll("-Dfile.encoding=[\\w\\d-]*", "-Dfile.encoding=!FILE_ENCODING!");
+ result = result.replaceAll("\\((.*)\\:\\d+\\)", "($1:!LINE_NUMBER!)");
+
+ int commandLineStart = result.indexOf("!JDK_HOME!");
+ while (commandLineStart != -1) {
+ final StringBuilder builder = new StringBuilder(result);
+ int i = commandLineStart + 1;
+ while (i < builder.length()) {
+ char c = builder.charAt(i);
+ if (c == '\n') break;
+ else if (c == File.separatorChar) builder.setCharAt(i, '\\');
+ i++;
+ }
+ result = builder.toString();
+ commandLineStart = result.indexOf("!JDK_HOME!", commandLineStart + 1);
+ }
+
+ result = stripQuotesAroundClasspath(result);
+
+ final Matcher matcher = Pattern.compile("-classpath\\s+(\\S+)\\s+").matcher(result);
+ while (matcher.find()) {
+ final String classPath = matcher.group(1);
+ final String[] classPathElements = classPath.split(File.pathSeparator);
+ if (sortClassPath) {
+ Arrays.sort(classPathElements);
+ }
+ final String sortedPath = StringUtil.join(classPathElements, ";");
+ result = StringUtil.replace(result, classPath, sortedPath);
+ }
+
+ result = JDI_BUG_OUTPUT_PATTERN_1.matcher(result).replaceAll("");
+ result = JDI_BUG_OUTPUT_PATTERN_2.matcher(result).replaceAll("");
+
+ return result;
+ }
+ catch (Exception exception) {
+ ex[0] = exception;
+ return null;
+ }
+ }
+ });
+
+
+ if (ex[0] != null) throw ex[0];
+
+ return actual;
+ }
+
+ protected String replaceAdditionalInOutput(String str) {
+ return str;
+ }
+
+ //do not depend on spaces in jdk path
+ private static String stripQuotesAroundClasspath(String result) {
+ final String clsp = "-classpath ";
+ int clspIdx = 0;
+ while (true) {
+ clspIdx = result.indexOf(clsp, clspIdx);
+ if (clspIdx <= -1) {
+ break;
+ }
+
+ final int spaceIdx = result.indexOf(" ", clspIdx + clsp.length());
+ if (spaceIdx > -1) {
+ result = result.substring(0, clspIdx) +
+ clsp +
+ StringUtil.stripQuotesAroundValue(result.substring(clspIdx + clsp.length(), spaceIdx)) +
+ result.substring(spaceIdx);
+ clspIdx += clsp.length();
+ } else {
+ break;
+ }
+ }
+ return result;
+ }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/SynchronizationBasedSemaphore.java b/java/testFramework/src/com/intellij/debugger/impl/SynchronizationBasedSemaphore.java
new file mode 100644
index 0000000..8c57cd3
--- /dev/null
+++ b/java/testFramework/src/com/intellij/debugger/impl/SynchronizationBasedSemaphore.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: Nov 17, 2009
+ */
+public class SynchronizationBasedSemaphore {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.Semaphore");
+ private int mySemaphore = 0;
+
+ public synchronized void down() {
+ mySemaphore++;
+ if (mySemaphore == 0) {
+ notifyAll();
+ }
+ }
+
+ public synchronized void up() {
+ mySemaphore--;
+ if (mySemaphore == 0) {
+ notifyAll();
+ }
+ }
+
+ public synchronized void waitFor() {
+ try {
+ while (mySemaphore > 0) {
+ wait();
+ }
+ }
+ catch (InterruptedException e) {
+ LOG.debug(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public synchronized boolean waitFor(final long timeout) {
+ try {
+ if (mySemaphore == 0) return true;
+ final long startTime = System.currentTimeMillis();
+ long waitTime = timeout;
+ while (mySemaphore > 0) {
+ wait(waitTime);
+ final long elapsed = System.currentTimeMillis() - startTime;
+ if (elapsed < timeout) {
+ waitTime = timeout - elapsed;
+ }
+ else {
+ break;
+ }
+ }
+ return mySemaphore == 0;
+ }
+ catch (InterruptedException e) {
+ LOG.debug(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java
new file mode 100644
index 0000000..075c681
--- /dev/null
+++ b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.execution;
+
+import com.intellij.debugger.impl.OutputChecker;
+import com.intellij.execution.configurations.JavaParameters;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.IdeaTestCase;
+import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.util.Alarm;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ui.UIUtil;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import org.jetbrains.annotations.NonNls;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class ExecutionTestCase extends IdeaTestCase {
+ private OutputChecker myChecker;
+
+ private int myTimeout;
+
+ private static AssertionFailedError ourAssertion;
+ private static final String CLASSES = "classes";
+ private static final String SRC = "src";
+
+ public ExecutionTestCase() {
+ setTimeout(300000); //30 seconds
+ }
+
+ public void setTimeout(int timeout) {
+ myTimeout = timeout;
+ }
+
+ protected abstract OutputChecker initOutputChecker();
+
+ protected abstract String getTestAppPath();
+
+ @Override
+ protected void setUp() throws Exception {
+ ourAssertion = null;
+ ensureCompiledAppExists();
+ myChecker = initOutputChecker();
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ExecutionTestCase.super.setUp();
+ }
+ catch (Throwable e) {
+ e.printStackTrace();
+ assertTrue(false);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void setUpModule() {
+ super.setUpModule();
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ final String modulePath = getTestAppPath();
+ final String srcPath = modulePath + File.separator + "src";
+ VirtualFile moduleDir = LocalFileSystem.getInstance().findFileByPath(modulePath.replace(File.separatorChar, '/'));
+ VirtualFile srcDir = LocalFileSystem.getInstance().findFileByPath(srcPath.replace(File.separatorChar, '/'));
+
+ final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule);
+ PsiTestUtil.removeAllRoots(myModule, rootManager.getSdk());
+ PsiTestUtil.addContentRoot(myModule, moduleDir);
+ PsiTestUtil.addSourceRoot(myModule, srcDir);
+ PsiTestUtil.setCompilerOutputPath(myModule, VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(getAppClassesPath())), false);
+ }
+ });
+ }
+
+ public void println(@NonNls String s, Key outputType) {
+ myChecker.println(s, outputType);
+ }
+
+ public void print(String s, Key outputType) {
+ myChecker.print(s, outputType);
+ }
+
+ @Override
+ protected void runBareRunnable(Runnable runnable) throws Throwable {
+ runnable.run();
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ myChecker.init(getTestName(true));
+ super.runTest();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ExecutionTestCase.super.tearDown();
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ }
+ }
+ });
+ if (ourAssertion != null) {
+ throw ourAssertion;
+ }
+ //myChecker.checkValid(getTestProjectJdk());
+ //probably some thread is destroyed right now because of log exception
+ //wait a little bit
+ synchronized (this) {
+ wait(300);
+ }
+ }
+
+ protected JavaParameters createJavaParameters(String mainClass) {
+ JavaParameters parameters = new JavaParameters();
+ parameters.getClassPath().add(getAppClassesPath());
+ parameters.setMainClass(mainClass);
+ parameters.setJdk(JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk());
+ return parameters;
+ }
+
+ protected OutputChecker getChecker() {
+ return myChecker;
+ }
+
+ protected String getAppDataPath() {
+ return getTestAppPath() + File.separator + "data";
+ }
+
+ protected String getAppOptionsPath() {
+ return getTestAppPath() + File.separator + "config" + File.separator + "options";
+ }
+
+ protected String getAppClassesPath() {
+ return getTestAppPath() + File.separator + "classes";
+ }
+
+ public void waitProcess(final ProcessHandler processHandler) {
+ Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, getTestRootDisposable());
+
+ final boolean[] isRunning = {true};
+ alarm.addRequest(new Runnable() {
+ @Override
+ public void run() {
+ boolean b;
+ synchronized (isRunning) {
+ b = isRunning[0];
+ }
+ if (b) {
+ processHandler.destroyProcess();
+ LOG.error("process was running over " + myTimeout / 1000 + " seconds. Interrupted. ");
+ }
+ }
+ }, myTimeout);
+ processHandler.waitFor();
+ synchronized (isRunning) {
+ isRunning[0] = false;
+ }
+ alarm.dispose();
+ }
+
+ public void waitFor(Runnable r) {
+ Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, getTestRootDisposable());
+ final Thread thread = Thread.currentThread();
+
+ final boolean[] isRunning = {true};
+ alarm.addRequest(new Runnable() {
+ @Override
+ public void run() {
+ boolean b;
+ synchronized (isRunning) {
+ b = isRunning[0];
+ }
+ if (b) {
+ thread.interrupt();
+ LOG.error("test was running over " + myTimeout / 1000 + " seconds. Interrupted. ");
+ }
+ }
+ }, myTimeout);
+ r.run();
+ synchronized (isRunning) {
+ isRunning[0] = false;
+ }
+ Thread.interrupted();
+ }
+
+// public static void fail(String message) {
+// ourAssertion = new AssertionFailedError(message);
+// }
+//
+// static public void assertTrue(String message, boolean condition) {
+// if (!condition)
+// fail(message);
+// }
+//
+// static public void assertTrue(boolean condition) {
+// assertTrue(null, condition);
+// }
+
+ private static final int CURRENT_VERSION = 6;
+ private static final String VERSION_FILE_NAME = "version-" + CURRENT_VERSION;
+ protected void ensureCompiledAppExists() throws Exception {
+ final String appPath = getTestAppPath();
+ final File classesDir = new File(appPath, CLASSES);
+ final File versionFile = new File(classesDir, VERSION_FILE_NAME);
+ if (!classesDir.exists() || !versionFile.exists() || !hasCompiledClasses(classesDir)) {
+ FileUtil.delete(classesDir);
+ classesDir.mkdirs();
+ if (compileTinyApp(appPath) != 0) {
+ throw new Exception("Failed to compile debugger test application.\nIt must be compiled in order to run debugger tests.\n" + appPath);
+ }
+ versionFile.createNewFile();
+ }
+ }
+
+ private int compileTinyApp(String appPath) {
+ final List<String> args = new ArrayList<String>();
+ args.add("-g");
+ args.add("-d");
+ args.add(new File(appPath, CLASSES).getPath());
+
+ final Class<TestCase> testCaseClass = TestCase.class;
+ final String junitLibRoot = PathManager.getResourceRoot(testCaseClass, "/" + testCaseClass.getName().replace('.', '/') + ".class");
+ if (junitLibRoot != null) {
+ args.add("-cp");
+ args.add(junitLibRoot);
+ }
+
+ final File[] files = new File(appPath, SRC).listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".java");
+ }
+ });
+ if (files == null) return 0; // Nothing to compile
+
+ for (File file : files) {
+ args.add(file.getPath());
+ }
+ return com.sun.tools.javac.Main.compile(ArrayUtil.toStringArray(args));
+ }
+
+ private boolean hasCompiledClasses(final File classesDir) {
+ for (File file : classesDir.listFiles()) {
+ if (file.isFile() && file.getName().endsWith(".class")) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
index a93ea6b..bfeac04 100644
--- a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
@@ -76,11 +76,11 @@
doTest(folderName, new GlobalInspectionToolWrapper(tool), "java 1.4", checkRange, runDeadCodeFirst);
}
- public void doTest(@NonNls String folderName, InspectionTool tool) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool) {
doTest(folderName, tool, "java 1.4");
}
- public void doTest(@NonNls String folderName, InspectionTool tool, final boolean checkRange) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool, final boolean checkRange) {
doTest(folderName, tool, "java 1.4", checkRange);
}
@@ -88,35 +88,35 @@
doTest(folderName, new LocalInspectionToolWrapper(tool), jdkName);
}
- public void doTest(@NonNls String folderName, InspectionTool tool, @NonNls final String jdkName) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool, @NonNls final String jdkName) {
doTest(folderName, tool, jdkName, false);
}
- public void doTest(@NonNls String folderName, InspectionTool tool, @NonNls final String jdkName, boolean checkRange) {
+ public void doTest(@NonNls String folderName, InspectionToolWrapper tool, @NonNls final String jdkName, boolean checkRange) {
doTest(folderName, tool, jdkName, checkRange, false);
}
public void doTest(@NonNls String folderName,
- InspectionTool tool,
+ InspectionToolWrapper toolWrapper,
@NonNls final String jdkName,
boolean checkRange,
boolean runDeadCodeFirst,
- InspectionTool... additional) {
+ InspectionToolWrapper... additional) {
final String testDir = getTestDataPath() + "/" + folderName;
- runTool(testDir, jdkName, runDeadCodeFirst, tool, additional);
+ runTool(testDir, jdkName, runDeadCodeFirst, toolWrapper, additional);
- InspectionTestUtil.compareToolResults(tool, checkRange, testDir);
+ InspectionTestUtil.compareToolResults(toolWrapper, checkRange, testDir);
}
- protected void runTool(@NonNls final String testDir, @NonNls final String jdkName, final InspectionTool tool) {
+ protected void runTool(@NonNls final String testDir, @NonNls final String jdkName, final InspectionToolWrapper tool) {
runTool(testDir, jdkName, false, tool);
}
protected void runTool(final String testDir,
final String jdkName,
boolean runDeadCodeFirst,
- final InspectionTool tool,
- InspectionTool... additional) {
+ @NotNull InspectionToolWrapper toolWrapper,
+ @NotNull InspectionToolWrapper... additional) {
final VirtualFile[] sourceDir = new VirtualFile[1];
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -132,14 +132,15 @@
AnalysisScope scope = createAnalysisScope(sourceDir[0].getParent());
InspectionManagerEx inspectionManager = (InspectionManagerEx)InspectionManager.getInstance(getProject());
- InspectionTool[] tools = runDeadCodeFirst ? new InspectionTool[]{new UnusedDeclarationInspection(), tool} : new InspectionTool[]{tool};
- tools = ArrayUtil.mergeArrays(tools, additional);
+ InspectionToolWrapper[] toolWrappers = runDeadCodeFirst ? new InspectionToolWrapper []{new GlobalInspectionToolWrapper(new UnusedDeclarationInspection()), toolWrapper} : new InspectionToolWrapper []{toolWrapper};
+ toolWrappers = ArrayUtil.mergeArrays(toolWrappers, additional);
final GlobalInspectionContextImpl globalContext =
- CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, getProject(), inspectionManager, tools);
+ CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, getProject(), inspectionManager, toolWrappers);
- InspectionTestUtil.runTool(tool, scope, globalContext, inspectionManager);
+ InspectionTestUtil.runTool(toolWrapper, scope, globalContext, inspectionManager);
}
+ @NotNull
protected AnalysisScope createAnalysisScope(VirtualFile sourceDir) {
PsiManager psiManager = PsiManager.getInstance(myProject);
return new AnalysisScope(psiManager.findDirectory(sourceDir));
diff --git a/java/testFramework/testFramework-java.iml b/java/testFramework/testFramework-java.iml
index 9d48d3d..ed67da5 100644
--- a/java/testFramework/testFramework-java.iml
+++ b/java/testFramework/testFramework-java.iml
@@ -22,6 +22,8 @@
<orderEntry type="module" module-name="relaxng" exported="" scope="TEST" />
<orderEntry type="module" module-name="idea-ui" exported="" />
<orderEntry type="module" module-name="external-system-impl" exported="" scope="TEST" />
+ <orderEntry type="module" module-name="debugger-impl" exported="" />
+ <orderEntry type="module" module-name="execution-openapi" exported="" />
</component>
<component name="copyright">
<Base>