Loading pom.xml +12 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,18 @@ <artifactId>flatlaf</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> </dependencies> <build> Loading src/main/java/jetklee/MemoryViewer.java +113 −13 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashMap; /** * Panel that displays memory of selected execution state Loading Loading @@ -44,8 +45,7 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { if (showAll) { showAllButton.setText("Hide"); displayCompleteMemory(currentState); } else { } else { showAllButton.setText("Show All"); displayShortMemory(currentState); } Loading Loading @@ -124,8 +124,9 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { return; } objectsList.setSelectedIndex(0); updatePlanes(); // objectsList.setSelectedIndex(0); // updatePlanes(); // displayObjectInfo(); } private void appendKeyValue(StyledDocument doc, String key, String value) { Loading @@ -148,6 +149,8 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { objectInfoPanel.removeAll(); if (objectsList.getSelectedIndex() < 0) { revalidate(); repaint(); return; } Loading Loading @@ -194,13 +197,14 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { appendKeyValue(doc, "Symbolic Address", currentObjectState.symAddress()); appendKeyValue(doc, "Copy-On-Write Owner", String.valueOf(currentObjectState.copyOnWriteOwner())); appendKeyValue(doc, "Read-Only", String.valueOf(currentObjectState.readOnly())); if (currentObjectState.segmentPlane() != null) { appendPlaneInfo(doc, "Segment Plane", currentObjectState.segmentPlane()); } if (currentObjectState.offsetPlane() != null) { appendPlaneInfo(doc, "Offset Plane", currentObjectState.offsetPlane()); } objectInfoPanel.revalidate(); objectInfoPanel.repaint(); } private void appendPlaneInfo(StyledDocument doc, String planeType, NodeMemory.Plane plane) { Loading @@ -222,18 +226,112 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { appendKeyValue(doc, "Initial Value", String.valueOf(plane.initialValue())); } private void getCompleteMemory(Node node, NodeMemory.Memory memory) { if (node == null) { return; private static NodeMemory.ObjectState mergeObjectState(NodeMemory.ObjectState a, NodeMemory.ObjectState b) { // copy all fields from a NodeMemory.Plane mergedSegmentPlane = mergePlane(a.segmentPlane(), b.segmentPlane()); NodeMemory.Plane mergedOffsetPlane = mergePlane(a.offsetPlane(), b.offsetPlane()); return new NodeMemory.ObjectState( a.objID(), a.type(), a.segment(), a.name(), a.size(), a.isLocal(), a.isGlobal(), a.isFixed(), a.isUserSpec(), a.isLazy(), a.symAddress(), a.copyOnWriteOwner(), a.readOnly(), mergedSegmentPlane, mergedOffsetPlane); } private static NodeMemory.Plane mergePlane(NodeMemory.Plane a, NodeMemory.Plane b) { if (a == null && b == null) { return null; } if (a == null) { return b; } if (b == null) { return a; } return new NodeMemory.Plane( a.type(), a.memoryObjectID(), a.rootObject(), a.sizeBound(), a.initialized(), a.symbolic(), a.initialValue(), mergeDiff(a.concreteStore(), b.concreteStore()), mergeDiff(a.concreteMask(), b.concreteMask()), mergeDiff(a.knownSymbolics(), b.knownSymbolics()), mergeUpdates(a.updates(), b.updates())); } private static NodeMemory.Updates mergeUpdates(NodeMemory.Updates a, NodeMemory.Updates b) { NodeMemory.Updates mergedUpdates = new NodeMemory.Updates(); if (a != null) { mergedUpdates.putAll(a); } if (b != null) { mergedUpdates.putAll(b); } return mergedUpdates; } public static NodeMemory.Diff mergeDiff(NodeMemory.Diff a, NodeMemory.Diff b) { NodeMemory.ByteMap mergedByteMap = new NodeMemory.ByteMap(); // Copy all entries from 'a' into 'mergedByteMap' a.additions().forEach((key, indices) -> { mergedByteMap.put(key, new ArrayList<>(indices)); }); // Delete all entries from 'b's deletions b.deletions().forEach((key, indices) -> { mergedByteMap.get(key).removeAll(indices); }); // Remove all empty entries from 'mergedByteMap' mergedByteMap.entrySet().removeIf(entry -> entry.getValue().isEmpty()); // Iterate over each addition in 'b' and merge it into 'mergedByteMap' b.additions().forEach((key, indices) -> { // If the key exists in 'mergedByteMap', merge the indices by adding all elements of 'indices' to 'mergedByteMap' mergedByteMap.merge(key, indices, (v1, v2) -> { v1.addAll(v2); return v1; }); }); getCompleteMemory(node.getParent(), memory); return new NodeMemory.Diff( mergedByteMap, // The complete state does not contain deletions new NodeMemory.ByteMap()); } private void displayCompleteMemory(Node node) { NodeMemory.Memory m = new NodeMemory.Memory(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); getCompleteMemory(node, m); displayTables(m); HashMap<Integer, NodeMemory.ObjectState> complete_memory = new HashMap<>(); ArrayList<Node> nodes = new ArrayList<>(); nodes.add(node); while (node.getParent() != null) { node = node.getParent(); nodes.add(node); } // Now we have the nodes in order from leaf to root, traverse them in reverse order for (int i = nodes.size() - 1; i >= 0; i--) { NodeMemory.Memory node_memory = nodes.get(i).getMemory().getMemory(); // Add newly added objects for (NodeMemory.ObjectState addition : node_memory.additions()) { complete_memory.put(addition.objID(), addition); } // Apply changes to changed objects for (NodeMemory.ObjectState change : node_memory.changes()) { NodeMemory.ObjectState oldObjectState = complete_memory.get(change.objID()); complete_memory.put(change.objID(), mergeObjectState(oldObjectState, change)); } // Remove deleted objects for (NodeMemory.Deletion deletion : node_memory.deletions()) { complete_memory.remove(deletion.objID()); } } NodeMemory.Memory memory = new NodeMemory.Memory(new ArrayList<>(complete_memory.values()), new ArrayList<>(), new ArrayList<>()); displayTables(memory); displayObjectInfo(); } Loading @@ -243,6 +341,8 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { } public void displayMemory(Node node) { showAllButton.setText("Show All"); showAll = false; currentState = node; currentMemory = node.getMemory().getMemory(); Loading Loading @@ -310,8 +410,8 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { if (isDeletion) { handleDeletionClick(selectedID); } else { displayObjectInfo(); updatePlanes(); displayObjectInfo(); } } Loading src/main/java/jetklee/NodeMemory.java +16 −3 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ import org.json.JSONObject; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; /** * Parses and holds information about execution state of the process tree Loading @@ -30,6 +29,9 @@ public class NodeMemory { public static class ByteMap extends HashMap<String, ArrayList<Integer>> { } public record AllocSite(String scope, String name, String code) { } public record Plane(PlaneType type, int memoryObjectID, String rootObject, int sizeBound, boolean initialized, boolean symbolic, int initialValue, Diff concreteStore, Diff concreteMask, Diff knownSymbolics, Loading @@ -50,7 +52,7 @@ public class NodeMemory { ArrayList<Deletion> deletions) { } public class Updates extends HashMap<String, String> { public static class Updates extends HashMap<String, String> { } public record Deletion(int objID, OperationType type) { Loading Loading @@ -101,6 +103,16 @@ public class NodeMemory { for (int i = 0; i < objectStatesJSON.length(); i++) { JSONObject objectStateJSON = objectStatesJSON.getJSONObject(i); // AllocSite allocSite = null; // if (objectStateJSON.has("allocSite")) { // JSONObject allocSiteJSON = objectStateJSON.getJSONObject("allocSite"); // allocSite = new AllocSite( // allocSiteJSON.getString("scope"), // allocSiteJSON.getString("name"), // allocSiteJSON.getString("code") // ); // } ObjectState objectState = new ObjectState( objectStateJSON.getInt("objID"), type, Loading @@ -115,6 +127,7 @@ public class NodeMemory { objectStateJSON.getString("symAddress"), objectStateJSON.getInt("copyOnWriteOwner"), objectStateJSON.getInt("readOnly") == 1, // allocSite, parsePlane(objectStateJSON, Plane.PlaneType.SEGMENT), parsePlane(objectStateJSON, Plane.PlaneType.OFFSET) ); Loading Loading @@ -187,7 +200,7 @@ public class NodeMemory { JSONObject updateJSON = updatesJSON.getJSONObject(i); String key = updateJSON.keys().next(); String value = updateJSON.getString(key); updates.put(key, value); updates.put(value, key); } } Loading src/main/java/jetklee/PlanePanel.java +7 −6 Original line number Diff line number Diff line Loading @@ -36,14 +36,15 @@ public class PlanePanel extends JPanel { updatePanel = new JPanel(new BorderLayout()); // Create a JSplitPane to display the concrete and symbolic panels side by side JSplitPane concreteSymbolicSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, concretePanel, symbolicPanel); concreteSymbolicSplitPane.setResizeWeight(0.5); // Divide space equally between panels JSplitPane bytesSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, concretePanel, symbolicPanel); bytesSplitPane.setResizeWeight(0.5); // Create a vertical JSplitPane to display the control panel and the combined concrete/symbolic panel JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlPanel, concreteSymbolicSplitPane); JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab("Bytes", bytesSplitPane); tabbedPane.addTab("Update", updatePanel); this.add(splitPane, BorderLayout.CENTER); this.add(controlPanel, BorderLayout.NORTH); this.add(tabbedPane, BorderLayout.CENTER); } private void clearTable(JPanel panel) { Loading src/test/java/TestMergeDiff.java 0 → 100644 +118 −0 Original line number Diff line number Diff line import jetklee.NodeMemory; import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; import java.util.Map; import static jetklee.MemoryViewer.mergeDiff; import static org.junit.jupiter.api.Assertions.assertEquals; public class TestMergeDiff { // Method to convert Map<String, List<Integer>> to ByteMap private static NodeMemory.ByteMap convertToByteMap(Map<String, List<Integer>> map) { NodeMemory.ByteMap byteMap = new NodeMemory.ByteMap(); for (Map.Entry<String, List<Integer>> entry : map.entrySet()) { byteMap.put(entry.getKey(), new ArrayList<>(entry.getValue())); } return byteMap; } @Test public void testMergeDiffSimple() { // Arrange: Set up diff1, diff2, and the expected result NodeMemory.Diff diff1 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(0, 1, 2, 3) )), // deletions new NodeMemory.ByteMap() ); NodeMemory.Diff diff2 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "1", List.of(1, 4) )), // deletions convertToByteMap(Map.of( "0", List.of(1, 2) )) ); NodeMemory.Diff expected = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(0, 3), "1", List.of(1, 4) )), // deletions new NodeMemory.ByteMap() ); // Act: Call the mergeDiff function NodeMemory.Diff result = mergeDiff(diff1, diff2); // check if the original diff1 and diff2 are not modified NodeMemory.Diff diff1Expected = new NodeMemory.Diff( convertToByteMap(Map.of( "0", List.of(0, 1, 2, 3) )), new NodeMemory.ByteMap() ); NodeMemory.Diff diff2Expected = new NodeMemory.Diff( convertToByteMap(Map.of( "1", List.of(1, 4) )), convertToByteMap(Map.of( "0", List.of(1, 2) )) ); assertEquals(diff1Expected, diff1, "The original diff1 is modified"); assertEquals(diff2Expected, diff2, "The original diff2 is modified"); // Assert: Check if the result matches the expected output assertEquals(expected, result, "The merged diff is incorrect"); } @Test public void testMergeDiffDuplicateKey() { // Arrange: Set up diff1, diff2, and the expected result NodeMemory.Diff diff1 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(0, 1, 2, 3) )), // deletions new NodeMemory.ByteMap() ); NodeMemory.Diff diff2 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "222", List.of(0) )), // deletions convertToByteMap(Map.of( "0", List.of(0) )) ); NodeMemory.Diff expected = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(1, 2, 3), "222", List.of(0) )), new NodeMemory.ByteMap() ); // Act: Call the mergeDiff function NodeMemory.Diff result = mergeDiff(diff1, diff2); // Assert: Check if the result matches the expected output assertEquals(expected, result, "The merged diff is incorrect"); } } Loading
pom.xml +12 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,18 @@ <artifactId>flatlaf</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> </dependencies> <build> Loading
src/main/java/jetklee/MemoryViewer.java +113 −13 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashMap; /** * Panel that displays memory of selected execution state Loading Loading @@ -44,8 +45,7 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { if (showAll) { showAllButton.setText("Hide"); displayCompleteMemory(currentState); } else { } else { showAllButton.setText("Show All"); displayShortMemory(currentState); } Loading Loading @@ -124,8 +124,9 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { return; } objectsList.setSelectedIndex(0); updatePlanes(); // objectsList.setSelectedIndex(0); // updatePlanes(); // displayObjectInfo(); } private void appendKeyValue(StyledDocument doc, String key, String value) { Loading @@ -148,6 +149,8 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { objectInfoPanel.removeAll(); if (objectsList.getSelectedIndex() < 0) { revalidate(); repaint(); return; } Loading Loading @@ -194,13 +197,14 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { appendKeyValue(doc, "Symbolic Address", currentObjectState.symAddress()); appendKeyValue(doc, "Copy-On-Write Owner", String.valueOf(currentObjectState.copyOnWriteOwner())); appendKeyValue(doc, "Read-Only", String.valueOf(currentObjectState.readOnly())); if (currentObjectState.segmentPlane() != null) { appendPlaneInfo(doc, "Segment Plane", currentObjectState.segmentPlane()); } if (currentObjectState.offsetPlane() != null) { appendPlaneInfo(doc, "Offset Plane", currentObjectState.offsetPlane()); } objectInfoPanel.revalidate(); objectInfoPanel.repaint(); } private void appendPlaneInfo(StyledDocument doc, String planeType, NodeMemory.Plane plane) { Loading @@ -222,18 +226,112 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { appendKeyValue(doc, "Initial Value", String.valueOf(plane.initialValue())); } private void getCompleteMemory(Node node, NodeMemory.Memory memory) { if (node == null) { return; private static NodeMemory.ObjectState mergeObjectState(NodeMemory.ObjectState a, NodeMemory.ObjectState b) { // copy all fields from a NodeMemory.Plane mergedSegmentPlane = mergePlane(a.segmentPlane(), b.segmentPlane()); NodeMemory.Plane mergedOffsetPlane = mergePlane(a.offsetPlane(), b.offsetPlane()); return new NodeMemory.ObjectState( a.objID(), a.type(), a.segment(), a.name(), a.size(), a.isLocal(), a.isGlobal(), a.isFixed(), a.isUserSpec(), a.isLazy(), a.symAddress(), a.copyOnWriteOwner(), a.readOnly(), mergedSegmentPlane, mergedOffsetPlane); } private static NodeMemory.Plane mergePlane(NodeMemory.Plane a, NodeMemory.Plane b) { if (a == null && b == null) { return null; } if (a == null) { return b; } if (b == null) { return a; } return new NodeMemory.Plane( a.type(), a.memoryObjectID(), a.rootObject(), a.sizeBound(), a.initialized(), a.symbolic(), a.initialValue(), mergeDiff(a.concreteStore(), b.concreteStore()), mergeDiff(a.concreteMask(), b.concreteMask()), mergeDiff(a.knownSymbolics(), b.knownSymbolics()), mergeUpdates(a.updates(), b.updates())); } private static NodeMemory.Updates mergeUpdates(NodeMemory.Updates a, NodeMemory.Updates b) { NodeMemory.Updates mergedUpdates = new NodeMemory.Updates(); if (a != null) { mergedUpdates.putAll(a); } if (b != null) { mergedUpdates.putAll(b); } return mergedUpdates; } public static NodeMemory.Diff mergeDiff(NodeMemory.Diff a, NodeMemory.Diff b) { NodeMemory.ByteMap mergedByteMap = new NodeMemory.ByteMap(); // Copy all entries from 'a' into 'mergedByteMap' a.additions().forEach((key, indices) -> { mergedByteMap.put(key, new ArrayList<>(indices)); }); // Delete all entries from 'b's deletions b.deletions().forEach((key, indices) -> { mergedByteMap.get(key).removeAll(indices); }); // Remove all empty entries from 'mergedByteMap' mergedByteMap.entrySet().removeIf(entry -> entry.getValue().isEmpty()); // Iterate over each addition in 'b' and merge it into 'mergedByteMap' b.additions().forEach((key, indices) -> { // If the key exists in 'mergedByteMap', merge the indices by adding all elements of 'indices' to 'mergedByteMap' mergedByteMap.merge(key, indices, (v1, v2) -> { v1.addAll(v2); return v1; }); }); getCompleteMemory(node.getParent(), memory); return new NodeMemory.Diff( mergedByteMap, // The complete state does not contain deletions new NodeMemory.ByteMap()); } private void displayCompleteMemory(Node node) { NodeMemory.Memory m = new NodeMemory.Memory(new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); getCompleteMemory(node, m); displayTables(m); HashMap<Integer, NodeMemory.ObjectState> complete_memory = new HashMap<>(); ArrayList<Node> nodes = new ArrayList<>(); nodes.add(node); while (node.getParent() != null) { node = node.getParent(); nodes.add(node); } // Now we have the nodes in order from leaf to root, traverse them in reverse order for (int i = nodes.size() - 1; i >= 0; i--) { NodeMemory.Memory node_memory = nodes.get(i).getMemory().getMemory(); // Add newly added objects for (NodeMemory.ObjectState addition : node_memory.additions()) { complete_memory.put(addition.objID(), addition); } // Apply changes to changed objects for (NodeMemory.ObjectState change : node_memory.changes()) { NodeMemory.ObjectState oldObjectState = complete_memory.get(change.objID()); complete_memory.put(change.objID(), mergeObjectState(oldObjectState, change)); } // Remove deleted objects for (NodeMemory.Deletion deletion : node_memory.deletions()) { complete_memory.remove(deletion.objID()); } } NodeMemory.Memory memory = new NodeMemory.Memory(new ArrayList<>(complete_memory.values()), new ArrayList<>(), new ArrayList<>()); displayTables(memory); displayObjectInfo(); } Loading @@ -243,6 +341,8 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { } public void displayMemory(Node node) { showAllButton.setText("Show All"); showAll = false; currentState = node; currentMemory = node.getMemory().getMemory(); Loading Loading @@ -310,8 +410,8 @@ public class MemoryViewer extends JPanel implements ListSelectionListener { if (isDeletion) { handleDeletionClick(selectedID); } else { displayObjectInfo(); updatePlanes(); displayObjectInfo(); } } Loading
src/main/java/jetklee/NodeMemory.java +16 −3 Original line number Diff line number Diff line Loading @@ -5,7 +5,6 @@ import org.json.JSONObject; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; /** * Parses and holds information about execution state of the process tree Loading @@ -30,6 +29,9 @@ public class NodeMemory { public static class ByteMap extends HashMap<String, ArrayList<Integer>> { } public record AllocSite(String scope, String name, String code) { } public record Plane(PlaneType type, int memoryObjectID, String rootObject, int sizeBound, boolean initialized, boolean symbolic, int initialValue, Diff concreteStore, Diff concreteMask, Diff knownSymbolics, Loading @@ -50,7 +52,7 @@ public class NodeMemory { ArrayList<Deletion> deletions) { } public class Updates extends HashMap<String, String> { public static class Updates extends HashMap<String, String> { } public record Deletion(int objID, OperationType type) { Loading Loading @@ -101,6 +103,16 @@ public class NodeMemory { for (int i = 0; i < objectStatesJSON.length(); i++) { JSONObject objectStateJSON = objectStatesJSON.getJSONObject(i); // AllocSite allocSite = null; // if (objectStateJSON.has("allocSite")) { // JSONObject allocSiteJSON = objectStateJSON.getJSONObject("allocSite"); // allocSite = new AllocSite( // allocSiteJSON.getString("scope"), // allocSiteJSON.getString("name"), // allocSiteJSON.getString("code") // ); // } ObjectState objectState = new ObjectState( objectStateJSON.getInt("objID"), type, Loading @@ -115,6 +127,7 @@ public class NodeMemory { objectStateJSON.getString("symAddress"), objectStateJSON.getInt("copyOnWriteOwner"), objectStateJSON.getInt("readOnly") == 1, // allocSite, parsePlane(objectStateJSON, Plane.PlaneType.SEGMENT), parsePlane(objectStateJSON, Plane.PlaneType.OFFSET) ); Loading Loading @@ -187,7 +200,7 @@ public class NodeMemory { JSONObject updateJSON = updatesJSON.getJSONObject(i); String key = updateJSON.keys().next(); String value = updateJSON.getString(key); updates.put(key, value); updates.put(value, key); } } Loading
src/main/java/jetklee/PlanePanel.java +7 −6 Original line number Diff line number Diff line Loading @@ -36,14 +36,15 @@ public class PlanePanel extends JPanel { updatePanel = new JPanel(new BorderLayout()); // Create a JSplitPane to display the concrete and symbolic panels side by side JSplitPane concreteSymbolicSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, concretePanel, symbolicPanel); concreteSymbolicSplitPane.setResizeWeight(0.5); // Divide space equally between panels JSplitPane bytesSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, concretePanel, symbolicPanel); bytesSplitPane.setResizeWeight(0.5); // Create a vertical JSplitPane to display the control panel and the combined concrete/symbolic panel JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlPanel, concreteSymbolicSplitPane); JTabbedPane tabbedPane = new JTabbedPane(); tabbedPane.addTab("Bytes", bytesSplitPane); tabbedPane.addTab("Update", updatePanel); this.add(splitPane, BorderLayout.CENTER); this.add(controlPanel, BorderLayout.NORTH); this.add(tabbedPane, BorderLayout.CENTER); } private void clearTable(JPanel panel) { Loading
src/test/java/TestMergeDiff.java 0 → 100644 +118 −0 Original line number Diff line number Diff line import jetklee.NodeMemory; import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; import java.util.Map; import static jetklee.MemoryViewer.mergeDiff; import static org.junit.jupiter.api.Assertions.assertEquals; public class TestMergeDiff { // Method to convert Map<String, List<Integer>> to ByteMap private static NodeMemory.ByteMap convertToByteMap(Map<String, List<Integer>> map) { NodeMemory.ByteMap byteMap = new NodeMemory.ByteMap(); for (Map.Entry<String, List<Integer>> entry : map.entrySet()) { byteMap.put(entry.getKey(), new ArrayList<>(entry.getValue())); } return byteMap; } @Test public void testMergeDiffSimple() { // Arrange: Set up diff1, diff2, and the expected result NodeMemory.Diff diff1 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(0, 1, 2, 3) )), // deletions new NodeMemory.ByteMap() ); NodeMemory.Diff diff2 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "1", List.of(1, 4) )), // deletions convertToByteMap(Map.of( "0", List.of(1, 2) )) ); NodeMemory.Diff expected = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(0, 3), "1", List.of(1, 4) )), // deletions new NodeMemory.ByteMap() ); // Act: Call the mergeDiff function NodeMemory.Diff result = mergeDiff(diff1, diff2); // check if the original diff1 and diff2 are not modified NodeMemory.Diff diff1Expected = new NodeMemory.Diff( convertToByteMap(Map.of( "0", List.of(0, 1, 2, 3) )), new NodeMemory.ByteMap() ); NodeMemory.Diff diff2Expected = new NodeMemory.Diff( convertToByteMap(Map.of( "1", List.of(1, 4) )), convertToByteMap(Map.of( "0", List.of(1, 2) )) ); assertEquals(diff1Expected, diff1, "The original diff1 is modified"); assertEquals(diff2Expected, diff2, "The original diff2 is modified"); // Assert: Check if the result matches the expected output assertEquals(expected, result, "The merged diff is incorrect"); } @Test public void testMergeDiffDuplicateKey() { // Arrange: Set up diff1, diff2, and the expected result NodeMemory.Diff diff1 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(0, 1, 2, 3) )), // deletions new NodeMemory.ByteMap() ); NodeMemory.Diff diff2 = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "222", List.of(0) )), // deletions convertToByteMap(Map.of( "0", List.of(0) )) ); NodeMemory.Diff expected = new NodeMemory.Diff( // additions convertToByteMap(Map.of( "0", List.of(1, 2, 3), "222", List.of(0) )), new NodeMemory.ByteMap() ); // Act: Call the mergeDiff function NodeMemory.Diff result = mergeDiff(diff1, diff2); // Assert: Check if the result matches the expected output assertEquals(expected, result, "The merged diff is incorrect"); } }