From eca21def753fadb8b199a1b56ba7389baa28356a Mon Sep 17 00:00:00 2001 From: sougandhs Date: Fri, 6 Dec 2024 19:07:50 +0530 Subject: [PATCH] Compare two objects in Variable View #531 This commit provides a new feature to compare elements of commonly used objects of similar types like Map, HashMap, LinkedHashMap, ConcurrentHashMap, Hashtable , IdentityHashMap, WeakHashMap, TreeMap, List, ArrayList, Stack, Vector, LinkedList, HashSet, LinkedHashSet, TreeSet, CopyOnWriteArraySet, Arrays, Wrappers and custom objects from Variables view and display differences of both in either diff viewer or dialog box. Fixes https://github.com/eclipse-platform/eclipse.platform/issues/531 --- .../compare/CompareArrayObjects.java | 25 + .../compare/CompareListObjects.java | 50 + .../compare/CompareMapObjects.java | 38 + .../compare/CompareNormalObjects.java | 34 + .../compare/CompareObjectsStringTest.java | 33 + .../compare/CompareSetObjects.java | 47 + .../jdt/debug/tests/AbstractDebugTest.java | 5 +- .../jdt/debug/tests/AutomatedSuite.java | 4 +- .../tests/variables/CompareObjectsTest.java | 523 ++++++++++ org.eclipse.jdt.debug.ui/plugin.properties | 5 +- org.eclipse.jdt.debug.ui/plugin.xml | 36 +- .../debug/ui/CompareElementsDiffView.java | 424 ++++++++ .../debug/ui/CompareElementsEditor.java | 75 ++ .../internal/debug/ui/DebugUIMessages.java | 32 + .../debug/ui/DebugUIMessages.properties | 33 +- .../internal/debug/ui/ObjectComparison.java | 970 ++++++++++++++++++ .../ui/actions/CompareObjectsAction.java | 609 +++++++++++ 17 files changed, 2937 insertions(+), 6 deletions(-) create mode 100644 org.eclipse.jdt.debug.tests/testprograms/compare/CompareArrayObjects.java create mode 100644 org.eclipse.jdt.debug.tests/testprograms/compare/CompareListObjects.java create mode 100644 org.eclipse.jdt.debug.tests/testprograms/compare/CompareMapObjects.java create mode 100644 org.eclipse.jdt.debug.tests/testprograms/compare/CompareNormalObjects.java create mode 100644 org.eclipse.jdt.debug.tests/testprograms/compare/CompareObjectsStringTest.java create mode 100644 org.eclipse.jdt.debug.tests/testprograms/compare/CompareSetObjects.java create mode 100644 org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/CompareObjectsTest.java create mode 100644 org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/CompareElementsDiffView.java create mode 100644 org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/CompareElementsEditor.java create mode 100644 org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/ObjectComparison.java create mode 100644 org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/actions/CompareObjectsAction.java diff --git a/org.eclipse.jdt.debug.tests/testprograms/compare/CompareArrayObjects.java b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareArrayObjects.java new file mode 100644 index 0000000000..cdf8242e57 --- /dev/null +++ b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareArrayObjects.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package compare; +import java.util.*; +public class CompareArrayObjects { + public static void main(String[] ecs) { + String[] args2 = {"asdasd","asdasd"}; + String[] args1 = {"asdasd","asdasd"}; + + Integer[] args11 = {1,2}; + Integer[] args12 = {2,3}; + int p = 100; + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/testprograms/compare/CompareListObjects.java b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareListObjects.java new file mode 100644 index 0000000000..c7345ed67f --- /dev/null +++ b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareListObjects.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package compare; + +import java.util.*; + +public class CompareListObjects { + public static void main(String[] ecs) { + List s1 = new ArrayList<>(Arrays.asList("apple", "banana")); + List s2 = new ArrayList<>(Arrays.asList("banana", "apple")); + List s3 = new ArrayList<>(Arrays.asList("apple", "banana")); + List s4 = new ArrayList<>(Arrays.asList("apple1", "banana")); + + List linkedList1 = new LinkedList<>(); + linkedList1.add(22); + linkedList1.add(12); + List linkedList2 = new LinkedList<>(); + linkedList2.add(12); + linkedList2.add(221); + + List Stack = new Stack<>(); + Stack.add("Cherry"); + Stack.add("Banana"); + Stack.add("Apple"); + List ArrayList = new ArrayList<>(); + ArrayList.add("Apple"); + ArrayList.add("Banana"); + ArrayList.add("Cherry"); + List Vector = new Vector<>(); + Vector.add("Banana"); + Vector.add("Cherry"); + Vector.add("Apple"); + List LinkedList = new LinkedList<>(); + LinkedList.add("Apple"); + LinkedList.add("Cherry"); + + int p = 100; + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/testprograms/compare/CompareMapObjects.java b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareMapObjects.java new file mode 100644 index 0000000000..a51a69f3bf --- /dev/null +++ b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareMapObjects.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package compare; +import java.util.*; +public class CompareMapObjects { + public static void main(String[] ecs) { + Map map8 = new TreeMap<>(); + map8.put(1, 4); + Map map9 = new TreeMap<>(); + map9.put(12, 4); + Map map2 = new HashMap<>(); + map2.put(1, 7); + Map map1 = new HashMap<>(); + map1.put(1, 7); + + Map map4 = new WeakHashMap<>(); + map4.put("key1", 17d); + Map map5 = new WeakHashMap<>(); + map5.put("key1", 7d); + + Map map6 = new IdentityHashMap<>(); + map6.put("key1", 7d); + Map map7 = new IdentityHashMap<>(); + map7.put("key2", 8d); + int p = 100; + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/testprograms/compare/CompareNormalObjects.java b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareNormalObjects.java new file mode 100644 index 0000000000..cb44b7a3c3 --- /dev/null +++ b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareNormalObjects.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package compare; +import java.util.*; + +class A { + public int custom; + public A(int custom) { + this.custom = custom; + } +} +public class CompareNormalObjects { + public static void main(String[] ecs) { + A a1 = new A(1); + A a2 = new A(2); + A a3 = a1; + Integer i1 = Integer.valueOf(10); + Integer i2 = Integer.valueOf(10); + Float f1 = Float.valueOf(12f); + Float f2 = Float.valueOf(112f); + int p = 100; + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/testprograms/compare/CompareObjectsStringTest.java b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareObjectsStringTest.java new file mode 100644 index 0000000000..348c56be41 --- /dev/null +++ b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareObjectsStringTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package compare; + +public class CompareObjectsStringTest { + public static void main(String[] ecs) { + String s1 = new String("eclipse"); + String s2 = new String("eclipse"); + + String s3 = "false1"; + String s4 = "false"; + + StringBuffer s5 = new StringBuffer("SDK"); + StringBuffer s6 = new StringBuffer("SDK"); + + StringBuilder s7 = new StringBuilder("Java"); + StringBuffer s8 = new StringBuffer("Java"); + + StringBuilder s9 = new StringBuilder("Java1"); + int p = 100; + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/testprograms/compare/CompareSetObjects.java b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareSetObjects.java new file mode 100644 index 0000000000..135b37b47f --- /dev/null +++ b/org.eclipse.jdt.debug.tests/testprograms/compare/CompareSetObjects.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package compare; +import java.util.*; +import java.util.concurrent.CopyOnWriteArraySet; +public class CompareSetObjects { + public static void main(String[] ecs) { + TreeSet xx11 = new TreeSet<>(); + xx11.add(1); + xx11.add(2); + TreeSet xx22 = new TreeSet<>(); + xx22.add(1); + xx22.add(21); + Set hashS1 = new HashSet<>(); + Set hashS2 = new HashSet<>(); + hashS1.add(1); + hashS1.add(21); + hashS2.add(1); + hashS2.add(21); + + Set linkedHashS1 = new LinkedHashSet<>(); + Set linkedHashS2 = new LinkedHashSet<>(); + linkedHashS1.add(1); + linkedHashS1.add(21); + linkedHashS2.add(1); + linkedHashS2.add(2); + + Set xx1 = new CopyOnWriteArraySet<>(); + xx1.add("one"); + xx1.add("two"); + Set xx2 = new CopyOnWriteArraySet<>(); + xx2.add("two"); + xx2.add("one"); + int p = 100; + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java index ae3ae33ffe..7215cb239f 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AbstractDebugTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -204,7 +204,8 @@ public abstract class AbstractDebugTest extends TestCase implements IEvaluation "StepResult2", "StepResult3", "StepUncaught", "TriggerPoint_01", "BulkThreadCreationTest", "MethodExitAndException", "Bug534319earlyStart", "Bug534319lateStart", "Bug534319singleThread", "Bug534319startBetwen", "MethodCall", "Bug538303", "Bug540243", "OutSync", "OutSync2", "ConsoleOutputUmlaut", "ErrorRecurrence", "ModelPresentationTests", "Bug565982", - "SuspendVMConditionalBreakpointsTestSnippet", "FileConditionSnippet2" }; + "SuspendVMConditionalBreakpointsTestSnippet", "FileConditionSnippet2", "compare.CompareObjectsStringTest", "compare.CompareListObjects", + "compare.CompareMapObjects", "compare.CompareSetObjects", "compare.CompareNormalObjects", "compare.CompareArrayObjects" }; /** * the default timeout diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java index 9a7311b9ff..f43af5d957 100644 --- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/AutomatedSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -153,6 +153,7 @@ import org.eclipse.jdt.debug.tests.ui.VirtualThreadsDebugViewTests; import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests; import org.eclipse.jdt.debug.tests.ui.presentation.ModelPresentationTests18; +import org.eclipse.jdt.debug.tests.variables.CompareObjectsTest; import org.eclipse.jdt.debug.tests.variables.DetailFormatterTests; import org.eclipse.jdt.debug.tests.variables.TestAnonymousInspect; import org.eclipse.jdt.debug.tests.variables.TestInstanceRetrieval; @@ -397,6 +398,7 @@ public AutomatedSuite() { addTest(new TestSuite(TriggerPointBreakpointsTests.class)); addTest(new TestSuite(JavaThreadEventHandlerTests.class)); addTest(new TestSuite(ConditionalBreakpointsWithFileClass.class)); + addTest(new TestSuite(CompareObjectsTest.class)); if (JavaProjectHelper.isJava8Compatible()) { addTest(new TestSuite(TestToggleBreakpointsTarget8.class)); diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/CompareObjectsTest.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/CompareObjectsTest.java new file mode 100644 index 0000000000..efc4582924 --- /dev/null +++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/variables/CompareObjectsTest.java @@ -0,0 +1,523 @@ +/******************************************************************************* + * Copyright (c) 2025 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation -- initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.debug.tests.variables; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; +import org.eclipse.jdt.debug.core.IJavaObject; +import org.eclipse.jdt.debug.core.IJavaThread; +import org.eclipse.jdt.debug.core.IJavaValue; +import org.eclipse.jdt.debug.core.IJavaVariable; +import org.eclipse.jdt.debug.tests.AbstractDebugTest; +import org.eclipse.jdt.internal.debug.ui.ObjectComparison; + +public class CompareObjectsTest extends AbstractDebugTest { + + private ObjectComparison objectComparision; + + public CompareObjectsTest(String name) { + super(name); + objectComparision = new ObjectComparison(); + } + + @Override + protected IJavaProject getProjectContext() { + return get14Project(); + } + + @SuppressWarnings("unchecked") + public void testForNormalStrings() throws Exception { // Test for String, StringBuffer & StringBuilder + + String typeName = "compare.CompareObjectsStringTest"; + IJavaLineBreakpoint bp = createLineBreakpoint(31, typeName); + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + int hitLine = 0; + assertTrue("Thread should be suspended", mainThread.isSuspended()); + hitLine = mainThread.getStackFrames()[0].getLineNumber(); + assertEquals("Didn't suspend at the expected line", 31, hitLine); + IJavaVariable s1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[2]; + IJavaVariable s2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[3]; + + IJavaVariable s3 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[4]; + IJavaVariable s4 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[5]; + + IJavaVariable s5 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[6]; + IJavaVariable s6 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[7]; + + IJavaVariable s7 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[8]; + IJavaVariable s8 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[9]; + + IJavaVariable s9 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[10]; + Map result = new HashMap<>(); + result.put(s1, objectComparision.objectValueExtraction((IJavaValue) s1.getValue())); + result.put(s2, objectComparision.objectValueExtraction((IJavaValue) s2.getValue())); + result = objectComparision.stringCompare(result); + Map compareResult = new HashMap<>(); + compareResult = (Map) result.get(s1); + assertThat(compareResult.get("ImmediateResult"), containsString("Same")); + result.clear(); + + result.put(s3, objectComparision.objectValueExtraction((IJavaValue) s3.getValue())); + result.put(s4, objectComparision.objectValueExtraction((IJavaValue) s4.getValue())); + result = objectComparision.stringCompare(result); + compareResult = (Map) result.get(s3); + assertThat(compareResult.get("ImmediateResult"), containsString("Different")); + result.clear(); + + result.put(s5, objectComparision.objectValueExtraction((IJavaValue) s5.getValue())); + result.put(s6, objectComparision.objectValueExtraction((IJavaValue) s6.getValue())); + result = objectComparision.stringCompare(result); + compareResult = (Map) result.get(s5); + assertThat(compareResult.get("ImmediateResult"), containsString("Same")); + result.clear(); + + result.put(s7, objectComparision.objectValueExtraction((IJavaValue) s7.getValue())); + result.put(s8, objectComparision.objectValueExtraction((IJavaValue) s8.getValue())); + result = objectComparision.stringCompare(result); + compareResult = (Map) result.get(s8); + assertThat(compareResult.get("ImmediateResult"), containsString("Same")); + result.clear(); + + result.put(s1, objectComparision.objectValueExtraction((IJavaValue) s1.getValue())); + result.put(s9, objectComparision.objectValueExtraction((IJavaValue) s9.getValue())); + result = objectComparision.stringCompare(result); + compareResult = (Map) result.get(s9); + assertThat(compareResult.get("ImmediateResult"), containsString("Different")); + result.clear(); + + bp.delete(); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + + @SuppressWarnings("unchecked") + public void testForLis() throws Exception { // Test for Lists, Stack, Vector, ArrayLists + + String typeName = "compare.CompareListObjects"; + IJavaLineBreakpoint bp = createLineBreakpoint(48, typeName); + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + int hitLine = 0; + assertTrue("Thread should be suspended", mainThread.isSuspended()); + hitLine = mainThread.getStackFrames()[0].getLineNumber(); + assertEquals("Didn't suspend at the expected line", 48, hitLine); + IJavaVariable s1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[2]; + IJavaVariable s2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[3]; + IJavaVariable s3 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[4]; + IJavaVariable s4 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[5]; + + IJavaVariable s5 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[6]; + IJavaVariable s6 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[7]; + + IJavaVariable stack = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[8]; + IJavaVariable arrayList = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[9]; + IJavaVariable vector = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[10]; + IJavaVariable linkedList = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[11]; + + Map result = new HashMap<>(); + result.put(s1, objectComparision.listElementsExtraction((IJavaObject) s1.getValue())); + result.put(s2, objectComparision.listElementsExtraction((IJavaObject) s2.getValue())); + result = objectComparision.compareSelectedLists(result); + Map compareResult = new HashMap<>(); + compareResult = (Map) result.get(s1); + String resultValue = compareResult.get("ImmediateResult"); + assertEquals("Object contains same elements as of s2 but in different order", resultValue); + result.clear(); + + result.put(s3, objectComparision.listElementsExtraction((IJavaObject) s3.getValue())); + result.put(s4, objectComparision.listElementsExtraction((IJavaObject) s4.getValue())); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(s3); + Object o = compareResult.get("Values"); + resultValue = o.toString(); + assertEquals("Element is actually missing - [apple1]", "[apple1]",resultValue); + result.clear(); + + result.put(s5, objectComparision.listElementsExtraction((IJavaObject) s5.getValue())); + result.put(s6, objectComparision.listElementsExtraction((IJavaObject) s6.getValue())); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(s6); + o = compareResult.get("Values"); + resultValue = o.toString(); + assertEquals("Element is actually missing - [22]","[22]" ,resultValue ); + result.clear(); + + result.put(stack, objectComparision.listElementsExtraction((IJavaObject) stack.getValue())); + result.put(arrayList, objectComparision.listElementsExtraction((IJavaObject) arrayList.getValue())); + result.put(vector, objectComparision.listElementsExtraction((IJavaObject) vector.getValue())); + result.put(linkedList, objectComparision.listElementsExtraction((IJavaObject) linkedList.getValue())); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(stack); + o = compareResult.get("ImmediateResult"); + resultValue = o.toString(); + assertThat(resultValue, containsString("same")); + compareResult = (Map) result.get(vector); + o = compareResult.get("ImmediateResult"); + resultValue = o.toString(); + assertThat(resultValue, containsString("different")); + compareResult = (Map) result.get(arrayList); + o = compareResult.get("ImmediateResult"); + resultValue = o.toString(); + assertThat(resultValue, containsString("same")); + compareResult = (Map) result.get(linkedList); + o = compareResult.get("MultiValues"); + resultValue = o.toString(); + assertThat(resultValue, containsString("{ArrayList=[Banana]")); + result.clear(); + + bp.delete(); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + + @SuppressWarnings("unchecked") + public void testForMaps() throws Exception { // Test for Maps + + String typeName = "compare.CompareMapObjects"; + IJavaLineBreakpoint bp = createLineBreakpoint(37, typeName); + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + int hitLine = 0; + assertTrue("Thread should be suspended", mainThread.isSuspended()); + hitLine = mainThread.getStackFrames()[0].getLineNumber(); + assertEquals("Didn't suspend at the expected line", 37, hitLine); + IJavaVariable map1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[2]; + IJavaVariable map2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[3]; + Map result = new HashMap<>(); + result.put(map1, objectComparision.mapElementsExtraction(map1)); + result.put(map2, objectComparision.mapElementsExtraction(map2)); + result = objectComparision.compareSelectedMaps(result); + Map compareResult = new HashMap<>(); + compareResult = (Map) result.get(map1); + Object o = compareResult.get("valSameInfo"); + String resultValue = o.toString(); + assertEquals("Values same as [map9]", resultValue); + o = compareResult.get("MapKeys"); + String resultKey = o.toString(); + assertEquals("[12]", resultKey); + result.clear(); + + IJavaVariable map3 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[4]; + IJavaVariable map4 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[5]; + result.put(map3, objectComparision.mapElementsExtraction(map3)); + result.put(map4, objectComparision.mapElementsExtraction(map4)); + result = objectComparision.compareSelectedMaps(result); + compareResult = (Map) result.get(map3); + o = compareResult.get("valSameInfo"); + resultValue = o.toString(); + assertEquals("Values same as [map1]", resultValue); + o = compareResult.get("keySameInfo"); + resultKey = o.toString(); + assertEquals("Keys same as [map1]", resultKey); + result.clear(); + + IJavaVariable map5 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[6]; + IJavaVariable map6 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[7]; + result.put(map5, objectComparision.mapElementsExtraction(map5)); + result.put(map6, objectComparision.mapElementsExtraction(map6)); + result = objectComparision.compareSelectedMaps(result); + compareResult = (Map) result.get(map6); + o = compareResult.get("MapValues"); + resultValue = o.toString(); + assertEquals("[17.0]", resultValue); + o = compareResult.get("keySameInfo"); + resultKey = o.toString(); + assertEquals("Keys same as [map4]", resultKey); + result.clear(); + + IJavaVariable map7 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[8]; + IJavaVariable map8 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[9]; + result.put(map7, objectComparision.mapElementsExtraction(map7)); + result.put(map8, objectComparision.mapElementsExtraction(map8)); + result = objectComparision.compareSelectedMaps(result); + compareResult = (Map) result.get(map7); + o = compareResult.get("MapValues"); + resultValue = o.toString(); + assertEquals("[8.0]", resultValue); + o = compareResult.get("MapKeys"); + resultKey = o.toString(); + assertEquals("[key2]", resultKey); + result.clear(); + + result.put(map1, objectComparision.mapElementsExtraction(map1)); + result.put(map2, objectComparision.mapElementsExtraction(map2)); + result.put(map3, objectComparision.mapElementsExtraction(map3)); + result.put(map4, objectComparision.mapElementsExtraction(map4)); + result.put(map5, objectComparision.mapElementsExtraction(map5)); + result.put(map6, objectComparision.mapElementsExtraction(map6)); + result.put(map7, objectComparision.mapElementsExtraction(map7)); + result.put(map8, objectComparision.mapElementsExtraction(map8)); + result = objectComparision.compareSelectedMaps(result); + compareResult = (Map) result.get(map7); + o = compareResult.get("MultiMapValues"); + resultValue = o.toString(); + assertThat(resultValue, containsString("map2")); + assertThat(resultValue, containsString("map8")); + assertThat(resultValue, containsString("map1")); + assertThat(resultValue, containsString("map7")); + o = compareResult.get("MultiMapKeys"); + resultKey = o.toString(); + assertThat(resultKey, containsString("map2")); + assertThat(resultKey, containsString("map8")); + assertThat(resultKey, containsString("map1")); + assertThat(resultKey, containsString("map7")); + result.clear(); + + bp.delete(); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + + @SuppressWarnings("unchecked") + public void testForSets() throws Exception { // Test for Sets + + String typeName = "compare.CompareSetObjects"; + IJavaLineBreakpoint bp = createLineBreakpoint(46, typeName); + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + int hitLine = 0; + assertTrue("Thread should be suspended", mainThread.isSuspended()); + hitLine = mainThread.getStackFrames()[0].getLineNumber(); + assertEquals("Didn't suspend at the expected line", 46, hitLine); + IJavaVariable s1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[2]; + IJavaVariable s2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[3]; + + Map result = new HashMap<>(); + result.put(s1, objectComparision.setElementsExtraction((IJavaObject) s1.getValue())); + result.put(s2, objectComparision.setElementsExtraction((IJavaObject) s2.getValue())); + result = objectComparision.compareSelectedLists(result); + Map compareResult = new HashMap<>(); + compareResult = (Map) result.get(s1); + Object o = compareResult.get("Values"); + String resultValue = o.toString(); + assertEquals("[21]", resultValue); + result.clear(); + + IJavaVariable s3 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[4]; + IJavaVariable s4 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[5]; + result.put(s3, objectComparision.setElementsExtraction((IJavaObject) s3.getValue())); + result.put(s4, objectComparision.setElementsExtraction((IJavaObject) s4.getValue())); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(s3); + o = compareResult.get("ImmediateResult"); + resultValue = o.toString(); + assertEquals("Object contains same elements as of hashS2", resultValue); + result.clear(); + + IJavaVariable linkedHashS1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[6]; + IJavaVariable linkedHashS2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[7]; + result.put(linkedHashS1, objectComparision.setElementsExtraction((IJavaObject) linkedHashS1.getValue())); + result.put(linkedHashS2, objectComparision.setElementsExtraction((IJavaObject) linkedHashS2.getValue())); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(linkedHashS2); + o = compareResult.get("Values"); + resultValue = o.toString(); + assertEquals("[21]", resultValue); + result.clear(); + + IJavaVariable copyWr1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[8]; + IJavaVariable copyWr2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[9]; + result.put(copyWr1, objectComparision.setElementsExtraction((IJavaObject) copyWr1.getValue())); + result.put(copyWr2, objectComparision.setElementsExtraction((IJavaObject) copyWr2.getValue())); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(copyWr1); + o = compareResult.get("ImmediateResult"); + resultValue = o.toString(); + assertEquals("Object contains same elements as of xx2", resultValue); + result.clear(); + + result.put(s1, objectComparision.setElementsExtraction((IJavaObject) s1.getValue())); + result.put(s2, objectComparision.setElementsExtraction((IJavaObject) s2.getValue())); + result.put(linkedHashS1, objectComparision.setElementsExtraction((IJavaObject) linkedHashS1.getValue())); + result.put(linkedHashS2, objectComparision.setElementsExtraction((IJavaObject) linkedHashS2.getValue())); + result.put(copyWr1, objectComparision.setElementsExtraction((IJavaObject) copyWr1.getValue())); + result.put(copyWr2, objectComparision.setElementsExtraction((IJavaObject) copyWr2.getValue())); + result.put(s3, objectComparision.setElementsExtraction((IJavaObject) s3.getValue())); + result.put(s4, objectComparision.setElementsExtraction((IJavaObject) s4.getValue())); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(copyWr1); + o = compareResult.get("MultiValues"); + resultValue = o.toString(); + assertThat(resultValue, containsString("linkedHashS2")); + assertThat(resultValue, containsString("linkedHashS1")); + assertThat(resultValue, containsString("hashS1")); + bp.delete(); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + + @SuppressWarnings("unchecked") + public void testForArrayObjects() throws Exception { // Test for Arrays + + String typeName = "compare.CompareArrayObjects"; + IJavaLineBreakpoint bp = createLineBreakpoint(23, typeName); + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + int hitLine = 0; + assertTrue("Thread should be suspended", mainThread.isSuspended()); + hitLine = mainThread.getStackFrames()[0].getLineNumber(); + assertEquals("Didn't suspend at the expected line", 23, hitLine); + IJavaVariable s1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[2]; + IJavaVariable s2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[3]; + + Map result = new HashMap<>(); + result.put(s1, objectComparision.arrayElementsExtraction(s1)); + result.put(s2, objectComparision.arrayElementsExtraction(s2)); + result = objectComparision.compareSelectedLists(result); + Map compareResult = new HashMap<>(); + compareResult = (Map) result.get(s1); + Object o = compareResult.get("ImmediateResult"); + String resultValue = o.toString(); + assertEquals("Object contains same elements as of args1", resultValue); + result.clear(); + + IJavaVariable s3 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[4]; + IJavaVariable s4 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[5]; + result.put(s3, objectComparision.arrayElementsExtraction(s3)); + result.put(s4, objectComparision.arrayElementsExtraction(s4)); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(s4); + o = compareResult.get("Values"); + resultValue = o.toString(); + assertEquals("[1]", resultValue); + result.clear(); + + result.put(s1, objectComparision.arrayElementsExtraction(s1)); + result.put(s2, objectComparision.arrayElementsExtraction(s2)); + result.put(s3, objectComparision.arrayElementsExtraction(s3)); + result.put(s4, objectComparision.arrayElementsExtraction(s4)); + result = objectComparision.compareSelectedLists(result); + compareResult = (Map) result.get(s3); + o = compareResult.get("MultiValues"); + resultValue = o.toString(); + assertThat(resultValue, containsString("args12")); + assertThat(resultValue, containsString("args1")); + + bp.delete(); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + + @SuppressWarnings("unchecked") + public void testForNormalObjects() throws Exception { // Test for normal objects + + String typeName = "compare.CompareNormalObjects"; + IJavaLineBreakpoint bp = createLineBreakpoint(32, typeName); + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + int hitLine = 0; + assertTrue("Thread should be suspended", mainThread.isSuspended()); + hitLine = mainThread.getStackFrames()[0].getLineNumber(); + assertEquals("Didn't suspend at the expected line", 32, hitLine); + IJavaVariable wrap1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[5]; + IJavaVariable wrap2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[6]; + + Map result = new HashMap<>(); + result.put(wrap1, objectComparision.objectValueExtraction((IJavaValue) wrap1.getValue())); + result.put(wrap2, objectComparision.objectValueExtraction((IJavaValue) wrap2.getValue())); + result = objectComparision.compareObjects(result); + Map compareResult = new HashMap<>(); + compareResult = (Map) result.get(wrap1); + Object o = compareResult.get("ImmediateResult"); + String resultValue = o.toString(); + assertEquals("Same value as of [i2]", resultValue); + result.clear(); + + IJavaVariable wrap3 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[7]; + IJavaVariable wrap4 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[8]; + result.put(wrap3, objectComparision.objectValueExtraction((IJavaValue) wrap3.getValue())); + result.put(wrap4, objectComparision.objectValueExtraction((IJavaValue) wrap4.getValue())); + result = objectComparision.compareObjects(result); + compareResult = (Map) result.get(wrap4); + o = compareResult.get("ImmediateResult"); + resultValue = o.toString(); + assertEquals("Different value in [f1]", resultValue); + + bp.delete(); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + + @SuppressWarnings("unchecked") + public void testForCustomObjects() throws Exception { // Test for custom objects + + String typeName = "compare.CompareNormalObjects"; + IJavaLineBreakpoint bp = createLineBreakpoint(32, typeName); + IJavaThread mainThread = null; + try { + mainThread = launchToBreakpoint(typeName); + int hitLine = 0; + assertTrue("Thread should be suspended", mainThread.isSuspended()); + hitLine = mainThread.getStackFrames()[0].getLineNumber(); + assertEquals("Didn't suspend at the expected line", 32, hitLine); + IJavaVariable wrap1 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[2]; + IJavaVariable wrap2 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[3]; + IJavaVariable wrap3 = (IJavaVariable) mainThread.getTopStackFrame().getVariables()[4]; + + Map result = new HashMap<>(); + result.put(wrap1, objectComparision.customObjectValueExtraction((IJavaObject) wrap1.getValue())); + result.put(wrap2, objectComparision.customObjectValueExtraction((IJavaObject) wrap2.getValue())); + result = objectComparision.compareCustomObjects(result); + Map compareResult = new HashMap<>(); + compareResult = (Map) result.get(wrap1); + Object o = compareResult.get("fields"); + String resultValue = o.toString(); + assertEquals("{custom=Different in [a2]}", resultValue); + compareResult = (Map) result.get(wrap2); + o = compareResult.get("fields"); + resultValue = o.toString(); + assertEquals("{custom=Different in [a1]}", resultValue); + result.clear(); + + result.put(wrap1, objectComparision.customObjectValueExtraction((IJavaObject) wrap1.getValue())); + result.put(wrap3, objectComparision.customObjectValueExtraction((IJavaObject) wrap3.getValue())); + result = objectComparision.compareCustomObjects(result); + compareResult = (Map) result.get(wrap1); + o = compareResult.get("fields"); + resultValue = o.toString(); + assertEquals("{custom=Same in [a3]}", resultValue); + + bp.delete(); + } finally { + terminateAndRemove(mainThread); + removeAllBreakpoints(); + } + } + +} diff --git a/org.eclipse.jdt.debug.ui/plugin.properties b/org.eclipse.jdt.debug.ui/plugin.properties index 202848d6a4..805de3ad88 100644 --- a/org.eclipse.jdt.debug.ui/plugin.properties +++ b/org.eclipse.jdt.debug.ui/plugin.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2022 IBM Corporation and others. +# Copyright (c) 2000, 2025 IBM Corporation and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -337,3 +337,6 @@ OpenFromClipboardAction.description = Opens a Java element or a Java stack trace OpenFromClipboardAction.name = Open from Clipboard VariablesView.name = Variables + +CompareObjects.label=Compare +CompareObjects.tooltip=Compare selected objects \ No newline at end of file diff --git a/org.eclipse.jdt.debug.ui/plugin.xml b/org.eclipse.jdt.debug.ui/plugin.xml index 718a2c9a99..c68914fc4c 100644 --- a/org.eclipse.jdt.debug.ui/plugin.xml +++ b/org.eclipse.jdt.debug.ui/plugin.xml @@ -1,7 +1,7 @@