diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XNamedValue.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XNamedValue.java new file mode 100644 index 000000000000..1f2fd77eb5c5 --- /dev/null +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XNamedValue.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2011 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.xdebugger; + +import com.intellij.xdebugger.frame.XValue; + +/** + * @author traff + */ +public abstract class XNamedValue extends XValue { + protected final String myName; + + public XNamedValue(String name) { + myName = name; + } + + public String getName() { + return myName; + } +} diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java new file mode 100644 index 000000000000..bc64be451c2a --- /dev/null +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java @@ -0,0 +1,224 @@ +/* + * Copyright 2000-2011 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.xdebugger; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.UsefulTestCase; +import com.intellij.util.ui.UIUtil; +import com.intellij.xdebugger.breakpoints.XBreakpoint; +import com.intellij.xdebugger.breakpoints.XBreakpointManager; +import com.intellij.xdebugger.breakpoints.XBreakpointType; +import com.intellij.xdebugger.breakpoints.XLineBreakpointType; +import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; +import com.intellij.xdebugger.frame.XExecutionStack; +import com.intellij.xdebugger.frame.XNavigatable; +import com.intellij.xdebugger.frame.XStackFrame; +import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointImpl; +import com.intellij.xdebugger.ui.DebuggerIcons; +import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +public class XDebuggerTestUtil { + private static final int TIMEOUT = 25000; + + private XDebuggerTestUtil() { + } + + public static > void assertBreakpointValidity(Project project, + VirtualFile file, + int line, + boolean validity, + String errorMessage, + Class> breakpointType) { + XLineBreakpointType type = (XLineBreakpointType)XDebuggerUtil.getInstance().findBreakpointType(breakpointType); + XBreakpointManager manager = XDebuggerManager.getInstance(project).getBreakpointManager(); + XLineBreakpointImpl breakpoint = (XLineBreakpointImpl)manager.findBreakpointAtLine(type, file, line); + Assert.assertNotNull(breakpoint); + Assert.assertEquals(validity ? DebuggerIcons.VERIFIED_BREAKPOINT_ICON : DebuggerIcons.INVALID_BREAKPOINT_ICON, breakpoint.getIcon()); + Assert.assertEquals(errorMessage, breakpoint.getErrorMessage()); + } + + public static void toggleBreakpoint(Project project, VirtualFile file, int line) { + XDebuggerUtil.getInstance().toggleLineBreakpoint(project, file, line); + } + + public static void assertPosition(XSourcePosition pos, VirtualFile file, int line) { + Assert.assertNotNull(pos); + Assert.assertEquals(file, pos.getFile()); + if (line != -1) Assert.assertEquals(line, pos.getLine()); + } + + public static void assertCurrentPosition(XDebugSession session, VirtualFile file, int line) { + assertPosition(session.getCurrentPosition(), file, line); + } + + public static XExecutionStack getActiveThread(XDebugSession session) { + return session.getSuspendContext().getActiveExecutionStack(); + } + + public static List collectStacks(XDebugSession session) throws InterruptedException { + return collectStacks(getActiveThread(session)); + } + + public static List collectStacks(XExecutionStack thread, XDebugSession session) throws InterruptedException { + if (thread == null) thread = getActiveThread(session); + + return collectStacks(thread); + } + + public static List collectStacks(XExecutionStack thread) throws InterruptedException { + XTestStackFrameContainer container = new XTestStackFrameContainer(); + thread.computeStackFrames(0, container); + return container.waitFor(TIMEOUT * 2).first; + } + + public static Pair evaluate(XDebugSession session, String expression) throws InterruptedException { + XDebuggerEvaluator evaluator = session.getCurrentStackFrame().getEvaluator(); + XTestEvaluationCallback callback = new XTestEvaluationCallback(); + evaluator.evaluate(expression, callback, session.getCurrentPosition()); + return callback.waitFor(TIMEOUT); + } + + public static void waitForSwing() throws InterruptedException, InvocationTargetException { + final com.intellij.util.concurrency.Semaphore s = new com.intellij.util.concurrency.Semaphore(); + s.down(); + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + s.up(); + } + }); + s.waitForUnsafe(); + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + public void run() { + } + }); + } + + @NotNull + public static XValue findVar(Collection vars, String name) { + for (XValue each : vars) { + if (each instanceof XNamedValue) { + if (((XNamedValue)each).getName().equals(name)) return each; + } + } + throw new AssertionError("var '" + name + "' not found"); + } + + public static XTestValueNode computePresentation(XValue value) throws InterruptedException { + XTestValueNode node = new XTestValueNode(); + if (value instanceof XNamedValue) { + node.myName = ((XNamedValue)value).getName(); + } + value.computePresentation(node); + Assert.assertTrue(node.waitFor(TIMEOUT)); + return node; + } + + public static void assertVariable(XValue var, String name, String type, String value, Boolean hasChildren) throws InterruptedException { + XTestValueNode node = computePresentation(var); + + Assert.assertEquals(name, node.myName); + if (type != null) Assert.assertEquals(type, node.myType); + if (value != null) Assert.assertEquals(value, node.myValue); + if (hasChildren != null) Assert.assertEquals((boolean)hasChildren, node.myHasChildren); + } + + public static void assertVariableValue(XValue var, String name, String value) throws InterruptedException { + assertVariable(var, name, null, value, null); + } + + public static void assertVariableValue(Collection vars, String name, String value) throws InterruptedException { + assertVariableValue(findVar(vars, name), name, value); + } + + public static void assertVariableValueMatches(Collection vars, String name, String valuePattern) throws InterruptedException { + assertVariableValueMatches(findVar(vars, name), name, valuePattern); + } + + public static void assertVariableValueMatches(XValue var, String name, String valuePattern) throws InterruptedException { + XTestValueNode node = computePresentation(var); + Assert.assertEquals(name, node.myName); + Assert.assertTrue(node.myValue, node.myValue.matches(valuePattern)); + } + + public static void assertVariables(List vars, String... names) throws InterruptedException { + List expectedNames = new ArrayList(Arrays.asList(names)); + + List actualNames = new ArrayList(); + for (XValue each : vars) { + actualNames.add(computePresentation(each).myName); + } + + Collections.sort(actualNames); + Collections.sort(expectedNames); + UsefulTestCase.assertOrderedEquals(actualNames, expectedNames); + } + + public static void assertSourcePosition(final XValue value, VirtualFile file, int offset) { + final XTestNavigatable n = new XTestNavigatable(); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + value.computeSourcePosition(n); + } + }); + Assert.assertNotNull(n.myPosition); + Assert.assertEquals(file, n.myPosition.getFile()); + Assert.assertEquals(offset, n.myPosition.getOffset()); + } + + public static boolean waitFor(Semaphore semaphore, long timeoutInMillis) throws InterruptedException { + return semaphore.tryAcquire(timeoutInMillis, TimeUnit.MILLISECONDS); + } + + public static void assertVariable(Collection vars, String name, String type, String value, Boolean hasChildren) + throws InterruptedException { + assertVariable(findVar(vars, name), name, type, value, hasChildren); + } + + public static class XTestStackFrameContainer extends XTestContainer implements XExecutionStack.XStackFrameContainer { + public void addStackFrames(@NotNull List stackFrames, boolean last) { + addChildren(stackFrames, last); + } + + public void errorOccured(String errorMessage) { + setErrorMessage(errorMessage); + } + } + + public static class XTestNavigatable implements XNavigatable { + private XSourcePosition myPosition; + + @Override + public void setSourcePosition(@Nullable XSourcePosition sourcePosition) { + myPosition = sourcePosition; + } + + public XSourcePosition getPosition() { + return myPosition; + } + } +} diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestCompositeNode.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestCompositeNode.java new file mode 100644 index 000000000000..361a9bccd335 --- /dev/null +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestCompositeNode.java @@ -0,0 +1,20 @@ +package com.intellij.xdebugger; + +import com.intellij.xdebugger.frame.XCompositeNode; +import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.frame.XValueChildrenList; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class XTestCompositeNode extends XTestContainer implements XCompositeNode { + @Override + public void addChildren(@NotNull XValueChildrenList children, boolean last) { + final List list = new ArrayList(); + for (int i = 0; i < children.size(); i++) { + list.add(children.getValue(i)); + } + addChildren(list, last); + } +} diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestContainer.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestContainer.java new file mode 100644 index 000000000000..751daf087e34 --- /dev/null +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestContainer.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2011 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.xdebugger; + +import com.intellij.openapi.util.Pair; +import com.intellij.util.SmartList; +import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.concurrent.Semaphore; + +public class XTestContainer { + private final List myChildren = new SmartList(); + private String myErrorMessage; + private final Semaphore myFinished = new Semaphore(0); + + public void addChildren(List children, boolean last) { + myChildren.addAll(children); + if (last) myFinished.release(); + } + + public void tooManyChildren(int remaining) { + myFinished.release(); + } + + public void setErrorMessage(@NotNull String errorMessage, @Nullable XDebuggerTreeNodeHyperlink link) { + setErrorMessage(errorMessage); + } + + public void setErrorMessage(@NotNull String errorMessage) { + myErrorMessage = errorMessage; + myFinished.release(); + } + + public boolean isObsolete() { + return false; + } + + public Pair, String> waitFor(long timeout) throws InterruptedException { + XDebuggerTestUtil.waitFor(myFinished, timeout); + return new Pair, String>(myChildren, myErrorMessage); + } +} diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestEvaluationCallback.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestEvaluationCallback.java new file mode 100644 index 000000000000..e81243e654b4 --- /dev/null +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestEvaluationCallback.java @@ -0,0 +1,31 @@ +package com.intellij.xdebugger; + +import com.intellij.openapi.util.Pair; +import com.intellij.xdebugger.frame.XValue; +import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.Semaphore; + +public class XTestEvaluationCallback extends com.intellij.xdebugger.impl.ui.tree.nodes.XEvaluationCallbackBase { + private XValue myResult; + private String myErrorMessage; + private final Semaphore myFinished = new Semaphore(0); + + @Override + public void evaluated(@NotNull XValue result) { + myResult = result; + myFinished.release(); + } + + @Override + public void errorOccurred(@NotNull String errorMessage) { + myErrorMessage = errorMessage; + myFinished.release(); + } + + public Pair waitFor(long timeoutInMilliseconds) throws InterruptedException { + Assert.assertTrue(XDebuggerTestUtil.waitFor(myFinished, timeoutInMilliseconds)); + return Pair.create(myResult, myErrorMessage); + } +} diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java new file mode 100644 index 000000000000..e0478e7ccf66 --- /dev/null +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java @@ -0,0 +1,65 @@ +package com.intellij.xdebugger; + +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.frame.XValueNode; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.concurrent.Semaphore; + +public class XTestValueNode implements XValueNode { + public String myName; + public String myType; + public String myValue; + public boolean myHasChildren; + + private final Semaphore myFinished = new Semaphore(0); + + @Override + public void setPresentation(@Nullable Icon icon, @NonNls @Nullable String type, @NonNls @NotNull String value, boolean hasChildren) { + myType = type; + myValue = value; + myHasChildren = hasChildren; + + myFinished.release(); + } + + @Override + public void setPresentation(@Nullable Icon icon, + @NonNls @Nullable String type, + @NonNls @NotNull String separator, + @NonNls @NotNull String value, + boolean hasChildren) { + setPresentation(icon, type, value, hasChildren); + } + + public void setPresentation(@NonNls @NotNull String name, + @Nullable Icon icon, + @NonNls @Nullable String type, + @NonNls @NotNull String value, + boolean hasChildren) { + setPresentation(icon, type, value, hasChildren); + } + + public void setPresentation(@NonNls @NotNull String name, + @Nullable Icon icon, + @NonNls @Nullable String type, + @NonNls @NotNull String separator, + @NonNls @NotNull String value, + boolean hasChildren) { + setPresentation(icon, type, value, hasChildren); + } + + public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) { + } + + public boolean isObsolete() { + return false; + } + + public boolean waitFor(long timeoutInMillis) throws InterruptedException { + return XDebuggerTestUtil.waitFor(myFinished, timeoutInMillis); + } +}