Test timing fixes

This commit is contained in:
dragonmacher 2022-09-22 12:07:19 -04:00
parent e79bd65944
commit b48fc9aad7
5 changed files with 530 additions and 674 deletions

View file

@ -24,6 +24,7 @@ import javax.swing.tree.TreePath;
import org.junit.Assert;
import org.junit.Before;
import docking.ActionContext;
import docking.action.DockingActionIf;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.services.ProgramTreeService;
@ -80,6 +81,12 @@ public abstract class AbstractProgramTreePluginTest extends AbstractGhidraHeaded
protected abstract ProgramDB buildProgram() throws Exception;
protected ActionContext getActionContext() {
ViewManagerComponentProvider provider = (ViewManagerComponentProvider) viewMgrService;
ActionContext context = runSwing(() -> provider.getActionContext(null));
return context;
}
protected void setTreeView(final String viewName) {
tree = plugin.getTree(viewName);
root = (ProgramNode) tree.getModel().getRoot();
@ -90,6 +97,16 @@ public abstract class AbstractProgramTreePluginTest extends AbstractGhidraHeaded
runSwing(() -> tree.setViewPaths(paths));
}
protected void setViewPaths(ProgramNode... nodes) {
runSwing(() -> {
TreePath[] paths = new TreePath[nodes.length];
for (int i = 0; i < nodes.length; i++) {
paths[i] = nodes[i].getTreePath();
}
tree.setViewPaths(paths);
});
}
protected TreePath[] getSelectionPaths() {
AtomicReference<TreePath[]> ref = new AtomicReference<>();
runSwing(() -> ref.set(tree.getSelectionPaths()));
@ -100,16 +117,33 @@ public abstract class AbstractProgramTreePluginTest extends AbstractGhidraHeaded
runSwing(() -> tree.setSelectionPaths(paths));
}
protected void setSelectionPaths(ProgramNode... nodes) {
runSwing(() -> {
TreePath[] paths = new TreePath[nodes.length];
for (int i = 0; i < nodes.length; i++) {
paths[i] = nodes[i].getTreePath();
}
tree.setSelectionPaths(paths);
});
}
protected void setSelectionPath(TreePath path) {
runSwing(() -> tree.setSelectionPath(path));
}
protected void setSelectionPath(ProgramNode node) {
runSwing(() -> {
tree.setSelectionPath(node.getTreePath());
});
}
protected void addSelectionPath(TreePath path) {
runSwing(() -> tree.addSelectionPath(path));
}
protected void visitNode(ProgramNode node) {
runSwing(() -> tree.visitNode(node));
waitForProgram(program);
}
protected void collapseNode(ProgramNode node) {

View file

@ -29,7 +29,6 @@ import javax.swing.tree.TreePath;
import org.junit.*;
import docking.ActionContext;
import docking.action.DockingActionIf;
import ghidra.app.services.GoToService;
import ghidra.program.database.ProgramBuilder;
@ -42,13 +41,12 @@ import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.program.util.GroupPath;
import ghidra.program.util.ProgramLocation;
import ghidra.util.Swing;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
private JTextField textField;// text field for cell editor
@Override
protected ProgramDB buildProgram() throws Exception {
//Default Tree
@ -89,7 +87,6 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
@Test
public void testProgramOpened() {
Memory mem = program.getMemory();
AddressSetView set = getView();
assertTrue(mem.hasSameAddresses(set));
assertTrue(mem.hasSameAddresses(cbPlugin.getView()));
@ -105,8 +102,6 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
int childCount = root.getChildCount();
addCodeUnits(root, set);
waitForProgram(program);
assertEquals(childCount + 1, root.getChildCount());
ProgramNode node = (ProgramNode) root.getChildAt(childCount);
assertEquals("0100101c", node.getName());
@ -157,16 +152,13 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
public void testCreateFolder() throws Exception {
int childCount = root.getChildCount();
setSelectionPath(root.getTreePath());
setSelectionPath(root);
DockingActionIf createFolderAction = getAction("Create Folder");
String newFolderName = tree.getNewFolderName();
runSwing(() -> {
createFolderAction.actionPerformed(new ActionContext());
tree.stopEditing();
});
performAction(createFolderAction);
commitEdit();
waitForProgram(program);
assertEquals(childCount + 1, root.getChildCount());
@ -184,16 +176,13 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
@Test
public void testCreateFragment() throws Exception {
int childCount = root.getChildCount();
setSelectionPath(root.getTreePath());
setSelectionPath(root);
DockingActionIf createFragmentAction = getAction("Create Fragment");
String newFragName = tree.getNewFragmentName();
runSwing(() -> {
createFragmentAction.actionPerformed(new ActionContext());
tree.stopEditing();
});
performAction(createFragmentAction);
commitEdit();
waitForProgram(program);
assertEquals(childCount + 1, root.getChildCount());
@ -208,7 +197,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
@Test
public void testCreateFolder2() throws Exception {
setSelectionPath(root.getTreePath());
setSelectionPath(root);
String newFolderName = tree.getNewFolderName();
tx(program, () -> {
@ -217,11 +206,8 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
int childCount = root.getChildCount();
DockingActionIf createFolderAction = getAction("Create Folder");
runSwing(() -> {
createFolderAction.actionPerformed(new ActionContext());
tree.stopEditing();
});
performAction(createFolderAction);
commitEdit();
waitForProgram(program);
assertEquals(childCount + 1, root.getChildCount());
@ -231,33 +217,22 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
@Test
public void testCreateFolderDuplicate() throws Exception {
setSelectionPath(root.getTreePath());
setSelectionPath(root);
String newName = tree.getNewFolderName();
DockingActionIf createFolderAction = getAction("Create Folder");
performAction(createFolderAction, getActionContext(), true);
waitForProgram(program);
JTextField[] newFolderTextField = new JTextField[1];
runSwing(() -> {
int row = tree.getRowForPath(tree.getEditingPath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
Container container = (Container) cellEditor.getTreeCellEditorComponent(tree,
tree.getEditingPath().getLastPathComponent(), true, true, true, row);
newFolderTextField[0] = (JTextField) container.getComponent(0);
newFolderTextField[0].setText("test1");
tree.stopEditing();
});
setEditorText("test1");
String[] text = new String[1];
runSwing(() -> text[0] = newFolderTextField[0].getText());
assertEquals(newName, text[0]);
String currentText = setEditorText("test1");
assertEquals(newName, currentText);
}
@Test
public void testCreateFragment2() throws Exception {
setSelectionPath(root.getTreePath());
setSelectionPath(root);
String newFragName = tree.getNewFragmentName();
tx(program, () -> {
@ -268,8 +243,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
DockingActionIf createFragmentAction = getAction("Create Fragment");
performAction(createFragmentAction, getActionContext(), true);
runSwing(() -> tree.stopEditing());
waitForProgram(program);
commitEdit();
waitFor(() -> root.getChildCount() == childCount + 1);
ProgramNode node = (ProgramNode) root.getChildAt(childCount);
@ -279,32 +253,20 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
@Test
public void testCreateFragmentDuplicate() throws Exception {
setSelectionPath(root.getTreePath());
setSelectionPath(root);
String newName = tree.getNewFragmentName();
DockingActionIf createFragmentAction = getAction("Create Fragment");
performAction(createFragmentAction, getActionContext(), true);
waitForProgram(program);
JTextField[] newFragmentTextField = new JTextField[1];
runSwing(() -> {
int row = tree.getRowForPath(tree.getEditingPath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
Container container = (Container) cellEditor.getTreeCellEditorComponent(tree,
tree.getEditingPath().getLastPathComponent(), true, true, true, row);
newFragmentTextField[0] = (JTextField) container.getComponent(0);
newFragmentTextField[0].setText("test1");
tree.stopEditing();
});
String[] text = new String[1];
runSwing(() -> text[0] = newFragmentTextField[0].getText());
assertEquals(newName, text[0]);
String currentText = setEditorText("test1");
assertEquals(newName, currentText);
}
@Test
public void testDeleteFolder() throws Exception {
setSelectionPath(root.getTreePath());
setSelectionPath(root);
String newFolderName = tree.getNewFolderName();
tx(program, () -> {
@ -313,15 +275,12 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
int childCount = root.getChildCount();
ProgramNode node = (ProgramNode) root.getChildAt(childCount - 1);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
DockingActionIf deleteAction = getAction("Delete");
performAction(deleteAction, getActionContext(), true);
waitForProgram(program);
runSwing(() -> root.getChildCount());
assertEquals(childCount - 1, root.getChildCount());
undo();
assertEquals(childCount, root.getChildCount());
@ -331,7 +290,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
@Test
public void testDeleteNotEmpty() throws Exception {
setSelectionPath(root.getTreePath());
setSelectionPath(root);
Address start = getAddr(0x0100101c);
Address end = getAddr(0x0100101f);
AddressSet set = new AddressSet();
@ -342,7 +301,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
waitFor(() -> root.getChildCount() == childCount + 1);
ProgramNode node = (ProgramNode) root.getChildAt(childCount);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
DockingActionIf deleteAction = getAction("Delete");
assertFalse(deleteAction.isEnabledForContext(getActionContext()));
@ -359,10 +318,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
});
ProgramNode mNode = root.getChild("MyModule");
runSwing(() -> {
setSelectionPath(mNode.getTreePath());
setSelectionPath(node.getTreePath());
});
setSelectionPaths(mNode, node);
DockingActionIf deleteAction = getAction("Delete");
assertTrue(deleteAction.isEnabledForContext(getActionContext()));
@ -383,8 +339,6 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
});
waitForProgram(program);
expandRoot();
buildNodeList();
@ -427,8 +381,6 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
m.setName("MyModule");
});
waitForProgram(program);
buildNodeList();
nodes = findNodes(newName);
assertEquals(5, nodes.length);
@ -453,24 +405,13 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
buildNodeList();
ProgramNode[] nodes = findNodes("submodule");
setSelectionPath(nodes[0].getTreePath());
setSelectionPath(nodes[0]);
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
assertTrue(action.isEnabledForContext(getActionContext()));
runSwing(() -> {
action.actionPerformed(new ActionContext());
int row = tree.getRowForPath(nodes[0].getTreePath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
Container container = (Container) cellEditor.getTreeCellEditorComponent(tree, nodes[0],
true, true, false, row);
textField = (JTextField) container.getComponent(0);
textField.setText("printf");
tree.stopEditing();
});
waitForSwing();
assertEquals("submodule", textField.getText());
performAction(action);
String currentText = setEditorText("printf");
assertEquals("submodule", currentText);
}
@Test
@ -485,25 +426,15 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
buildNodeList();
ProgramNode[] nodes = findNodes("strcpy");
setSelectionPath(nodes[0].getTreePath());
setSelectionPath(nodes[0]);
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
assertTrue(action.isEnabledForContext(getActionContext()));
runSwing(() -> {
action.actionPerformed(new ActionContext());
int row = tree.getRowForPath(nodes[0].getTreePath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
Container container = (Container) cellEditor.getTreeCellEditorComponent(tree, nodes[0],
true, true, true, row);
textField = (JTextField) container.getComponent(0);
textField.setText(".data");
tree.stopEditing();
});
waitForSwing();
performAction(action);
String currentText = setEditorText(".data");
ProgramModule module = getModule(root, "Module-1");
ProgramFragment f = getFragment(module, ".data");
assertEquals(f.getName(), textField.getText());
assertEquals(f.getName(), currentText);
}
@Test
@ -517,23 +448,12 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
buildNodeList();
ProgramNode[] nodes = findNodes("Module-1");
setSelectionPath(nodes[0].getTreePath());
setSelectionPath(nodes[0]);
DockingActionIf action = getAction(plugin, "Rename folder/fragment");
assertTrue(action.isEnabledForContext(getActionContext()));
runSwing(() -> {
action.actionPerformed(new ActionContext());
int row = tree.getRowForPath(nodes[0].getTreePath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
Container container = (Container) cellEditor.getTreeCellEditorComponent(tree, nodes[0],
true, true, false, row);
textField = (JTextField) container.getComponent(0);
textField.setText("My Module-1");
tree.stopEditing();
});
assertEquals("My Module-1", textField.getText());
performAction(action);
String currentText = setEditorText("My Module-1");
assertEquals("My Module-1", currentText);
waitForProgram(program);
assertEquals("My Module-1", nodes[0].getModule().getName());
}
@ -581,7 +501,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
buildNodeList();
nodes = findNodes(m2.getName());
assertEquals(5, nodes.length);
ArrayList<?> nodeList = tree.getNodeList();
List<?> nodeList = tree.getNodeList();
for (Object element : nodeList) {
node = (ProgramNode) element;
if (node.getAllowsChildren() && !node.isLeaf()) {
@ -649,7 +569,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode bNode = aNode.getChild("B");
visitNode(bNode);
ProgramNode cNode = bNode.getChild("C");
setViewPaths(new TreePath[] { cNode.getTreePath(), textNode.getTreePath() });
setViewPaths(cNode, textNode);
AddressSet set2 = new AddressSet();
set2.add(textNode.getFragment());
set2.add(cNode.getModule().getAddressSet());
@ -690,7 +610,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode funcNode = root.getChild("Functions");
visitNode(funcNode);
ProgramNode sscanfNode = funcNode.getChild("sscanf");
setViewPaths(new TreePath[] { sscanfNode.getTreePath() });
setViewPaths(sscanfNode);
GoToService goToService = tool.getService(GoToService.class);
goToService.goTo(new ProgramLocation(program, sscanfNode.getFragment().getMinAddress()));
@ -701,7 +621,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
public void testGoToViewIcon() {
setTreeView("Main Tree");
actionMgr.setProgramTreeView("Main Tree", tree);
runSwing(() -> actionMgr.setProgramTreeView("Main Tree", tree));
clearView();
@ -723,7 +643,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(0);
ProgramNode n2 = (ProgramNode) root.getChildAt(1);
setSelectionPaths(new TreePath[] { node.getTreePath() });
setSelectionPaths(node);
// replace view so we can remove each node
setViewPaths(getSelectionPaths());
@ -750,7 +670,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(0);
ProgramNode n2 = (ProgramNode) root.getChildAt(1);
setSelectionPaths(new TreePath[] { node.getTreePath(), n2.getTreePath() });
setSelectionPaths(node, n2);
setViewPaths(getSelectionPaths());
@ -788,15 +708,15 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
if (node == null) {
Assert.fail("Expected a Functions module!");
}
setSelectionPaths(new TreePath[] { node.getTreePath() });
setSelectionPaths(node);
DockingActionIf replaceAction = getAction("Replace");
performAction(replaceAction, true);
performAction(replaceAction);
assertTrue(getView().hasSameAddresses(node.getModule().getAddressSet()));
DockingActionIf removeAction = getAction("Remove");
performAction(removeAction, true);
performAction(removeAction);
assertTrue(getView().isEmpty());
assertTrue(cbPlugin.getView().isEmpty());
@ -807,20 +727,16 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
setTreeView("Main Tree");
ProgramNode node = root.getChild("Functions");
if (node == null) {
Assert.fail("Expected a Functions module!");
}
tree.addSelectionPaths(new TreePath[] { node.getTreePath() });
assertNotNull("Expected a Functions module!", node);
setSelectionPath(node);
setViewPaths(getSelectionPaths());
ProgramNode finalNode = node;
runSwing(() -> tree.removeFromView(finalNode.getTreePath()));
int row = getRowForPath(node.getTreePath());
Component comp = tree.getCellRenderer()
.getTreeCellRendererComponent(tree, node, true, false, true, row, false);
Component comp = runSwing(() -> tree.getCellRenderer()
.getTreeCellRendererComponent(tree, node, true, false, true, row, false));
assertEquals(ResourceManager.loadImage(DnDTreeCellRenderer.CLOSED_FOLDER),
((JLabel) comp).getIcon());
}
@ -833,15 +749,14 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode node1 = (ProgramNode) root.getChildAt(1);
ProgramNode node2 = (ProgramNode) root.getChildAt(2);
setSelectionPaths(
new TreePath[] { node0.getTreePath(), node1.getTreePath(), node2.getTreePath() });
setSelectionPaths(node0, node1, node2);
setViewPaths(getSelectionPaths());
// now remove two of these from the view
setSelectionPaths(new TreePath[] { node0.getTreePath(), node2.getTreePath() });
setSelectionPaths(node0, node2);
DockingActionIf removeAction = getAction("Remove");
performAction(removeAction, true);
performAction(removeAction);
AddressSet set = new AddressSet();
set.add(node0.getFragment());
@ -877,8 +792,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
visitNode(othernodes[0]);
ProgramNode otherchild1 = (ProgramNode) othernodes[0].getFirstChild();
setViewPaths(new TreePath[] { child1.getTreePath(), child3.getTreePath(),
otherchild1.getTreePath() });
setViewPaths(child1, child3, otherchild1);
AddressSet set = new AddressSet();
set.add(child1.getFragment());
set.add(child3.getFragment());
@ -888,10 +802,10 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
// collapse the test folder and remove the view
collapseNode(nodes[0]);
setSelectionPath(nodes[0].getTreePath());
setSelectionPath(nodes[0]);
DockingActionIf removeAction = getAction("Remove");
performAction(removeAction, true);
performAction(removeAction);
// verify that all the descendants of the folder are removed from the view
assertFalse(getView().contains(child1.getFragment()));
@ -909,21 +823,20 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(6);
visitNode(node);
ProgramNode child = (ProgramNode) node.getChildAt(0);
setSelectionPath(child.getTreePath());
setSelectionPath(child);
DockingActionIf replaceAction = getAction("Replace");
performAction(replaceAction, true);
performAction(replaceAction);
assertTrue(getView().hasSameAddresses(child.getFragment()));
assertTrue(getView().hasSameAddresses(cbPlugin.getView()));
assertTrue(getView().hasSameAddresses(viewMgrService.getCurrentView()));
int row = getRowForPath(child.getTreePath());
Component comp = tree.getCellRenderer()
.getTreeCellRendererComponent(tree, child, true, false, true, row, false);
Component comp = runSwing(() -> tree.getCellRenderer()
.getTreeCellRendererComponent(tree, child, true, false, true, row, false));
assertEquals(ResourceManager.loadImage(DnDTreeCellRenderer.VIEWED_FRAGMENT),
((JLabel) comp).getIcon());
}
@Test
@ -931,7 +844,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
setTreeView("Main Tree");
ProgramNode node = (ProgramNode) root.getChildAt(6);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
DockingActionIf replaceAction = getAction("Replace");
assertTrue(replaceAction.isEnabledForContext(getActionContext()));
@ -947,7 +860,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode textNode = (ProgramNode) root.getChildAt(1);
ProgramNode dataNode = (ProgramNode) root.getChildAt(2);
setViewPaths(new TreePath[] { textNode.getTreePath(), dataNode.getTreePath() });
setViewPaths(textNode, dataNode);
// select DLLs folder
ProgramNode dllsNode = (ProgramNode) root.getChildAt(6);
@ -959,10 +872,10 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
// set a folder not in the view and a fragment that is not a
// descendant of that folder, and not in the view
setSelectionPaths(new TreePath[] { dllsNode.getTreePath(), sscanfNode.getTreePath() });
setSelectionPaths(dllsNode, sscanfNode);
DockingActionIf replaceAction = getAction("Replace");
performAction(replaceAction, true);
performAction(replaceAction);
AddressSet set = new AddressSet();
set.add(dllsNode.getModule().getAddressSet());
@ -988,10 +901,9 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
public void testDoubleClick2() {
setTreeView("Main Tree");
ProgramNode node = root.getChild(".data");
TreePath[] paths = new TreePath[] { node.getTreePath() };
setViewPaths(paths);
setViewPaths(node);
int row = getRowForPath(paths[0]);
int row = getRowForPath(node.getTreePath());
Rectangle rect = tree.getRowBounds(row);
clickMouse(tree, MouseEvent.BUTTON1, rect.x, rect.y, 2, 0);
@ -1011,11 +923,10 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode dllsNode = (ProgramNode) nodes[0].getChildAt(6);
int dllsCount = dllsNode.getChildCount();
setSelectionPath(dllsNode.getTreePath());
setSelectionPath(dllsNode);
DockingActionIf mergeAction = getAction("Merge");
performAction(mergeAction, true);
performAction(mergeAction);
waitForProgram(program);
int count = nodes[0].getChildCount();
@ -1045,7 +956,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
ProgramNode[] bNodes = findNodes("B");
ProgramNode[] dNodes = findNodes("D");
setSelectionPaths(new TreePath[] { dNodes[0].getTreePath(), bNodes[0].getTreePath() });
setSelectionPaths(dNodes[0], bNodes[0]);
DockingActionIf mergeAction = getAction("Merge");
performAction(mergeAction, getActionContext(), true);
@ -1061,13 +972,13 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
expandRoot();
ProgramNode node = (ProgramNode) root.getChildAt(2);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
DockingActionIf mergeAction = getAction("Merge");
assertFalse(mergeAction.isEnabledForContext(getActionContext()));
ProgramNode fnode = (ProgramNode) root.getChildAt(6);
setSelectionPaths(new TreePath[] { node.getTreePath(), fnode.getTreePath() });
setSelectionPaths(node, fnode);
DockingActionIf mergeAction2 = getAction("Merge");
assertTrue(mergeAction2.isEnabledForContext(getActionContext()));
@ -1080,7 +991,7 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
expandRoot();
ProgramNode node = (ProgramNode) root.getChildAt(2);
ProgramNode fnode = (ProgramNode) root.getChildAt(6);
setViewPaths(new TreePath[] { node.getTreePath(), fnode.getTreePath() });
setViewPaths(node, fnode);
runSwing(() -> env.saveRestoreToolState());
@ -1198,13 +1109,13 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
assertTrue(showAction.isEnabledForContext(getActionContext()));
String[] treeNames = program.getListing().getTreeNames();
performAction(showAction, true);
performAction(showAction);
JPopupMenu menu = plugin.getPopupMenu();
assertNotNull(menu);
Component[] comps = menu.getComponents();
ArrayList<Component> list = new ArrayList<>();
List<Component> list = new ArrayList<>();
for (Component comp : comps) {
if (comp instanceof JMenuItem) {
list.add(comp);
@ -1226,16 +1137,33 @@ public class ProgramTreePlugin1Test extends AbstractProgramTreePluginTest {
}
}
private String setEditorText(String text) {
JTextField editorTextField = runSwing(() -> {
int row = tree.getRowForPath(tree.getEditingPath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
Container container = (Container) cellEditor.getTreeCellEditorComponent(tree,
tree.getEditingPath().getLastPathComponent(), true, true, true, row);
JTextField textField = (JTextField) container.getComponent(0);
textField.setText(text);
commitEdit();
return textField;
});
waitForProgram(program);
return runSwing(() -> editorTextField.getText());
}
private void commitEdit() {
runSwing(() -> tree.stopEditing());
if (!Swing.isSwingThread()) {
waitForProgram(program);
}
}
//==================================================================================================
// Private Methods
//==================================================================================================
private ActionContext getActionContext() {
ViewManagerComponentProvider provider = (ViewManagerComponentProvider) viewMgrService;
ActionContext context = runSwing(() -> provider.getActionContext(null));
return context;
}
private void assertPluginViewAppliedToTool() {
AddressSet pluginAddrs = plugin.getView();
assertTrue(pluginAddrs.hasSameAddresses(cbPlugin.getView()));

View file

@ -34,7 +34,7 @@ import ghidra.program.model.listing.*;
import resources.ResourceManager;
/**
* Tests for cut/copy/paste in the Program tree.
* Tests for cut/copy/paste in the Program tree.
*/
public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
@ -98,7 +98,6 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
@After
public void tearDown() throws Exception {
env.release(program);
env.dispose();
}
@ -107,18 +106,18 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(0);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
assertTrue(copyAction.isEnabled());
performAction(copyAction, true);
performAction(copyAction);
node = (ProgramNode) root.getChildAt(5);
int origCount = node.getChildCount();
setSelectionPath(node.getTreePath());
setSelectionPath(node);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
// wait for events to go out
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
expandNode(node);
ProgramNode child = (ProgramNode) node.getChildAt(node.getChildCount() - 1);
assertEquals(".text", child.getName());
@ -141,59 +140,55 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
public void testCopyPasteActionEnabled() throws Exception {
ProgramNode node = (ProgramNode) root.getChildAt(0);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
assertTrue(copyAction.isEnabled());
performAction(copyAction);
performAction(copyAction, true);
setSelectionPath(root.getTreePath());
setSelectionPath(root);
// fragment is already in root
assertTrue(!pasteAction.isEnabled());
assertFalse(pasteAction.isEnabled());
// cannot paste fragment to another fragment
node = (ProgramNode) root.getChildAt(1);
setSelectionPath(root.getTreePath());
assertTrue(!pasteAction.isEnabled());
setSelectionPath(root);
assertFalse(pasteAction.isEnabled());
expandNode(root);
// destination folder is a descendant of the copied folder
node = (ProgramNode) root.getChildAt(9);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
assertTrue(copyAction.isEnabled());
performAction(copyAction, true);
ProgramNode[] nodes = findNodes("C");
setSelectionPath(nodes[0].getTreePath());
setSelectionPath(nodes[0]);
assertTrue(!pasteAction.isEnabled());
assertFalse(pasteAction.isEnabled());
// fragment is already in the destination folder
int transactionID = program.startTransaction("Test");
ProgramFragment f = program.getListing().getFragment("Main Tree", "USER32.DLL");
ProgramModule funcModule = program.getListing().getModule("Main Tree", "Functions");
funcModule.add(f);
program.endTransaction(transactionID, true);
program.flushEvents();
tx(program, () -> {
ProgramFragment f = program.getListing().getFragment("Main Tree", "USER32.DLL");
ProgramModule funcModule = program.getListing().getModule("Main Tree", "Functions");
funcModule.add(f);
});
node = (ProgramNode) root.getChildAt(6);// Functions
ProgramNode fnode = (ProgramNode) node.getChildAt(3);
// select USER32.DLL
setSelectionPath(fnode.getTreePath());
performAction(copyAction, true);
// select USER32.DLL
setSelectionPath(fnode);
performAction(copyAction);
// select DLLs
node = (ProgramNode) root.getChildAt(6);
setSelectionPath(node.getTreePath());
assertTrue(!pasteAction.isEnabled());
setSelectionPath(node);
assertFalse(pasteAction.isEnabled());
//cannot copy root
setSelectionPath(root.getTreePath());
assertTrue(!copyAction.isEnabled());
setSelectionPath(root);
assertFalse(copyAction.isEnabled());
}
@Test
@ -203,13 +198,13 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode pasteNode = (ProgramNode) root.getChildAt(5);// DLLs
int childCount = pasteNode.getChildCount();
setSelectionPath(cpNode.getTreePath());
setSelectionPath(cpNode);
performAction(copyAction, true);
setSelectionPath(pasteNode.getTreePath());
performAction(copyAction);
setSelectionPath(pasteNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
assertEquals(childCount + 1, pasteNode.getChildCount());
ProgramNode node = (ProgramNode) pasteNode.getChildAt(childCount);
@ -231,25 +226,23 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(6);// Functions
ProgramNode cnode1 = (ProgramNode) node.getChildAt(0);
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
setSelectionPaths(new TreePath[] { cnode1.getTreePath(), cnode2.getTreePath() });
setSelectionPaths(cnode1, cnode2);
assertTrue(copyAction.isEnabled());
performAction(copyAction, true);
performAction(copyAction);
// create a new module and paste fragments there
int transactionID = program.startTransaction("test");
root.getModule().createModule("Test");
program.endTransaction(transactionID, true);
program.flushEvents();
tx(program, () -> {
root.getModule().createModule("Test");
});
ProgramNode destNode = (ProgramNode) root.getChildAt(root.getChildCount() - 1);
setSelectionPath(destNode.getTreePath());
setSelectionPath(destNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
performAction(pasteAction);
waitForProgram(program);
program.flushEvents();
visitNode(destNode);
assertEquals(2, destNode.getChildCount());
}
@Test
@ -258,25 +251,24 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(6);// Functions
ProgramNode cnode1 = (ProgramNode) node.getChildAt(0);
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
setSelectionPaths(new TreePath[] { cnode1.getTreePath(), cnode2.getTreePath() });
setSelectionPaths(cnode1, cnode2);
assertTrue(copyAction.isEnabled());
performAction(copyAction, true);
performAction(copyAction);
// create a new module and paste fragments there
int transactionID = program.startTransaction("test");
ProgramModule m = root.getModule().createModule("Test");
ProgramModule subr = listing.getModule("Main Tree", "Subroutines");
subr.add(m);
program.endTransaction(transactionID, true);
program.flushEvents();
tx(program, () -> {
ProgramModule m = root.getModule().createModule("Test");
ProgramModule subr = listing.getModule("Main Tree", "Subroutines");
subr.add(m);
});
// get node for "Test"
ProgramNode destNode = (ProgramNode) root.getChildAt(root.getChildCount() - 1);
setSelectionPath(destNode.getTreePath());
setSelectionPath(destNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
performAction(pasteAction);
waitForProgram(program);
program.flushEvents();
expandNode(root);
assertEquals(2, destNode.getChildCount());
// make sure other occurrences show pasted fragments
@ -306,19 +298,19 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(6);// Functions
ProgramNode cnode1 = (ProgramNode) node.getChildAt(0);
ProgramNode cnode2 = (ProgramNode) node.getChildAt(1);
setSelectionPaths(new TreePath[] { cnode1.getTreePath(), cnode2.getTreePath() });
setSelectionPaths(cnode1, cnode2);
assertTrue(copyAction.isEnabled());
performAction(copyAction, true);
performAction(copyAction);
// get node for DLLs
ProgramNode destNode = (ProgramNode) root.getChildAt(5);
int dllCount = destNode.getChildCount();
setSelectionPath(destNode.getTreePath());
setSelectionPath(destNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
performAction(pasteAction);
waitForProgram(program);
program.flushEvents();
expandNode(root);
assertEquals(dllCount + 2, destNode.getChildCount());
// make sure other occurrences show pasted fragments
@ -347,16 +339,15 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
// that is not in the view
ProgramNode node = (ProgramNode) root.getChildAt(6);// Functions
// set the view to Functions
setSelectionPath(node.getTreePath());
setViewPaths(new TreePath[] { node.getTreePath() });
performAction(copyAction, true);
setSelectionPath(node);
setViewPaths(node);
performAction(copyAction);
ProgramNode subrNode = (ProgramNode) root.getChildAt(8);
setSelectionPath(subrNode.getTreePath());
setSelectionPath(subrNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
// verify the view is not affected
assertTrue(plugin.getView().hasSameAddresses(node.getModule().getAddressSet()));
@ -376,20 +367,19 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode node = (ProgramNode) root.getChildAt(6);// Functions
// set the view to Functions
setViewPaths(new TreePath[] { node.getTreePath() });
setViewPaths(node);
AddressSetView origSet = node.getModule().getAddressSet();
// select Subroutines (not in the view)
ProgramNode subrNode = (ProgramNode) root.getChildAt(8);
setSelectionPath(subrNode.getTreePath());
setSelectionPath(subrNode);
performAction(copyAction, true);
setSelectionPath(node.getTreePath());
performAction(copyAction);
setSelectionPath(node);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
assertTrue(plugin.getView().hasSameAddresses(node.getModule().getAddressSet()));
undo();
@ -405,18 +395,17 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
// that is not in the view
ProgramNode node = (ProgramNode) root.getChildAt(6);// Functions
// set the view to Functions
setViewPaths(new TreePath[] { node.getTreePath() });
setViewPaths(node);
ProgramNode child = (ProgramNode) node.getChildAt(0);
setSelectionPath(child.getTreePath());
performAction(copyAction, true);
setSelectionPath(child);
performAction(copyAction);
ProgramNode subrNode = (ProgramNode) root.getChildAt(8);
setSelectionPath(subrNode.getTreePath());
setSelectionPath(subrNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
// verify the view is not affected
assertTrue(plugin.getView().hasSameAddresses(node.getModule().getAddressSet()));
@ -435,19 +424,18 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode fnode = (ProgramNode) node.getChildAt(0);// 01002a91
AddressSet fnodeSet = new AddressSet(fnode.getFragment());
setSelectionPath(fnode.getTreePath());
setSelectionPath(fnode);
assertTrue(cutAction.isEnabled());
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
ProgramNode funcNode = (ProgramNode) root.getChildAt(6);// Functions
ProgramNode destNode = (ProgramNode) funcNode.getChildAt(0);// doStuff fragment
// now select the doStuff fragment as the destination node
setSelectionPath(destNode.getTreePath());
performAction(pasteAction, true);
setSelectionPath(destNode);
performAction(pasteAction);
waitForProgram(program);
program.flushEvents();
assertTrue(destNode.getFragment().contains(fnodeSet));
assertNull(listing.getFragment("Main Tree", "01002a91"));
assertEquals(childCount - 1, node.getChildCount());
@ -457,7 +445,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
node = (ProgramNode) root.getChildAt(8);// Subroutines
funcNode = (ProgramNode) root.getChildAt(6);// Functions
destNode = (ProgramNode) funcNode.getChildAt(0);// doStuff fragment
assertTrue(!destNode.getFragment().contains(fnodeSet));
assertFalse(destNode.getFragment().contains(fnodeSet));
assertNotNull(listing.getFragment("Main Tree", "01002a91"));
expandNode(node);
@ -478,30 +466,29 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
@Test
public void testCutFragmentToFragment2() throws Exception {
// pasted fragment should appear in more than one folder
int transactionID = program.startTransaction("test");
ProgramFragment f = listing.getFragment("Main Tree", "01002a91");
ProgramModule m = listing.getModule("Main Tree", "DLLs");
m.add(f);
program.endTransaction(transactionID, true);
tx(program, () -> {
ProgramFragment f = listing.getFragment("Main Tree", "01002a91");
ProgramModule m = listing.getModule("Main Tree", "DLLs");
m.add(f);
});
ProgramNode node = (ProgramNode) root.getChildAt(8);// Subroutines
int childCount = node.getChildCount();
ProgramNode fnode = (ProgramNode) node.getChildAt(0);// 01002a91
AddressSet fnodeSet = new AddressSet(fnode.getFragment());
setSelectionPath(fnode.getTreePath());
setSelectionPath(fnode);
assertTrue(cutAction.isEnabled());
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
ProgramNode funcNode = (ProgramNode) root.getChildAt(6);// Functions
ProgramNode destNode = (ProgramNode) funcNode.getChildAt(0);// ghidra fragment
// now select the ghidra fragment as the destination node
setSelectionPath(destNode.getTreePath());
performAction(pasteAction, true);
setSelectionPath(destNode);
performAction(pasteAction);
waitForProgram(program);
program.flushEvents();
assertTrue(destNode.getFragment().contains(fnodeSet));
assertNull(listing.getFragment("Main Tree", "01002a91"));
assertEquals(childCount - 1, node.getChildCount());
@ -512,7 +499,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
funcNode = (ProgramNode) root.getChildAt(6);// Functions
destNode = (ProgramNode) funcNode.getChildAt(0);// doStuff fragment
assertTrue(!destNode.getFragment().contains(fnodeSet));
assertFalse(destNode.getFragment().contains(fnodeSet));
assertNotNull(listing.getFragment("Main Tree", "01002a91"));
expandNode(node);
@ -534,18 +521,18 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
public void testCutFragmentToFolder() throws Exception {
ProgramNode node = (ProgramNode) root.getChildAt(0);
setSelectionPath(node.getTreePath());
setSelectionPath(node);
assertTrue(cutAction.isEnabled());
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
node = (ProgramNode) root.getChildAt(5);//DLLs
int origCount = node.getChildCount();
setSelectionPath(node.getTreePath());
setSelectionPath(node);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
// wait for events to go out
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
expandNode(node);
ProgramNode child = (ProgramNode) node.getChildAt(node.getChildCount() - 1);
assertEquals(".text", child.getName());
@ -569,13 +556,13 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode destNode = (ProgramNode) root.getChildAt(5);// DLLs
int childCount = destNode.getChildCount();
setSelectionPath(cNode.getTreePath());
setSelectionPath(cNode);
// cut Functions
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
setSelectionPath(destNode.getTreePath());// paste at DLLs
performAction(cutAction);
setSelectionPath(destNode);// paste at DLLs
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
assertEquals(childCount + 1, destNode.getChildCount());
ProgramNode node = (ProgramNode) destNode.getChildAt(childCount);
@ -605,7 +592,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
public void testCutFolderExpanded() throws Exception {
// cut a folder that has descendants expanded,
// expand the destination and paste.
// The pasted folder should retain its expansion state.
// The pasted folder should retain its expansion state.
ProgramNode stringsNode = root.getChild("Strings");
visitNode(stringsNode);
ProgramNode lnode = stringsNode.getChild("L");
@ -614,16 +601,16 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
// Strings, L are expanded
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// cut Strings
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
// paste at Functions
ProgramNode funcNode = root.getChild("Functions");
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
waitForProgram(program);
// Strings, L should be expanded
@ -637,7 +624,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
public void testCutFolderExpanded2() throws Exception {
// cut a folder that has descendants expanded,
// collapse the destination folder and paste.
// The destination folder should remain collapsed.
// The destination folder should remain collapsed.
ProgramNode stringsNode = root.getChild("Strings");
visitNode(stringsNode);
ProgramNode lnode = stringsNode.getChild("L");
@ -646,17 +633,16 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
// Strings, L are expanded
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// cut Strings
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
// paste at Functions
ProgramNode funcNode = root.getChild("Functions");
collapsePath(funcNode.getTreePath());
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
// Functions should remain collapsed
assertTrue(tree.isCollapsed(funcNode.getTreePath()));
@ -666,25 +652,24 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
@Test
public void testCutFolderCollapsed() throws Exception {
// cut a folder that is collapsed;
// cut a folder that is collapsed;
// expand the destination and paste.
// The pasted folder should be collapsed.
// The pasted folder should be collapsed.
ProgramNode stringsNode = root.getChild("Strings");
visitNode(stringsNode);
collapsePath(stringsNode.getTreePath());
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// cut Strings
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
// paste at Functions
ProgramNode funcNode = root.getChild("Functions");
expandPath(funcNode.getTreePath());
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
stringsNode = funcNode.getChild("Strings");
assertTrue(tree.isCollapsed(stringsNode.getTreePath()));
@ -693,7 +678,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
@Test
public void testCutFolderCollapsed2() throws Exception {
// cut folder is collapsed,
// cut folder is collapsed,
// destination folder is collapsed.
// Paste the the folder; the destination folder
// remains collapsed
@ -702,19 +687,17 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
collapsePath(stringsNode.getTreePath());
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// cut Strings
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
// paste at Functions
ProgramNode funcNode = root.getChild("Functions");
visitNode(funcNode);
collapsePath(funcNode.getTreePath());
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
assertTrue(tree.isCollapsed(funcNode.getTreePath()));
}
@ -743,11 +726,9 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
// select Strings (has no fragments)
ProgramNode stringsNode = root.getChild("Strings");
visitNode(stringsNode);
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
assertEquals(3, stringsNode.getChildCount());
assertEquals("rsrc", stringsNode.getChildAt(1).toString());
@ -807,7 +788,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
addSelectionPath(cutNodes[i].getTreePath());
}
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
// select a destination fragment
ProgramNode stringsNode = root.getChild("Strings");
@ -815,15 +796,15 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode cNode = stringsNode.getChild("L");
visitNode(cNode);
ProgramNode fnode = cNode.getChild("testl");
setSelectionPath(fnode.getTreePath());
setSelectionPath(fnode);
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
for (ProgramNode cutNode : cutNodes) {
assertNull(listing.getFragment("Main Tree", cutNode.getName()));
assertEquals(0, findNodes(cutNode.getName()).length);
}
// note: >10 events causes the tree to get reloaded...
root = (ProgramNode) tree.getModel().getRoot();
stringsNode = root.getChild("Strings");
@ -852,34 +833,33 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
@Test
public void testCutFolderToFragment() throws Exception {
// select a folder that has fragments and subfolders that have
// select a folder that has fragments and subfolders that have
// fragments, and cut.
// select a fragment not in the hierarchy of the cut folder
// and paste.
// verify that the destination fragment contains all code units
// from the cut folder's descendants;
// verify that the cut folder and all of its descendants are
// verify that the cut folder and all of its descendants are
// removed from the program.
AddressSet set = new AddressSet();
// first create a folder and add fragments and folders to it
int transactionID = program.startTransaction("test");
ProgramModule m = root.getModule().createModule("Test");
m.add(listing.getFragment("Main Tree", ".text"));
m.add(listing.getFragment("Main Tree", ".debug_data"));
m.add(listing.getModule("Main Tree", "Subroutines"));
m.add(listing.getModule("Main Tree", "Functions"));
program.endTransaction(transactionID, true);
set.add(m.getAddressSet());
program.flushEvents();
tx(program, () -> {
ProgramModule m = root.getModule().createModule("Test");
m.add(listing.getFragment("Main Tree", ".text"));
m.add(listing.getFragment("Main Tree", ".debug_data"));
m.add(listing.getModule("Main Tree", "Subroutines"));
m.add(listing.getModule("Main Tree", "Functions"));
set.add(m.getAddressSet());
});
expandNode(root);
ProgramNode testNode = root.getChild("Test");
setSelectionPath(testNode.getTreePath());
setSelectionPath(testNode);
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
performAction(cutAction);
// paste at 010074d4
ProgramNode stringsNode = root.getChild("Strings");
@ -887,12 +867,12 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode cNode = stringsNode.getChild("L");
visitNode(cNode);
ProgramNode fnode = cNode.getChild("testl");
setSelectionPath(fnode.getTreePath());
setSelectionPath(fnode);
performAction(pasteAction);
waitForProgram(program);
performAction(pasteAction, true);
program.flushEvents();
root = (ProgramNode) tree.getModel().getRoot();
// reacquire nodes
expandNode(root);
stringsNode = root.getChild("Strings");
visitNode(stringsNode);
@ -919,7 +899,7 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
visitNode(cNode);
fnode = cNode.getChild("testl");
assertTrue(!fnode.getFragment().contains(set));
assertFalse(fnode.getFragment().contains(set));
expandNode(root);
testNode = root.getChild("Test");
assertNotNull(testNode);
@ -945,7 +925,6 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
assertEquals(0, findNodes("Functions").length);
assertEquals(0, findNodes(".text").length);
assertEquals(0, findNodes(".debug_data").length);
}
@Test
@ -956,35 +935,34 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
ProgramNode node = root.getChild("DLLs");
// set the view to DLLs
setSelectionPath(node.getTreePath());
setSelectionPath(node);
setViewPaths(new TreePath[] { node.getTreePath() });
performAction(copyAction, true);
performAction(copyAction);
ProgramNode everythingNode = root.getChild("Everything");
setSelectionPath(everythingNode.getTreePath());
setSelectionPath(everythingNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
performAction(pasteAction);
waitForProgram(program);
program.flushEvents();
// cut a fragment in the view and paste onto a collapsed folder
// not in the view
// the first occurrence of the folder should indicate that one of
// not in the view
// the first occurrence of the folder should indicate that one of
// its descendants is in the view
ProgramNode dataNode = root.getChild(".data");
setSelectionPath(dataNode.getTreePath());
setSelectionPath(dataNode);
setViewPaths(new TreePath[] { dataNode.getTreePath() });
performAction(cutAction);
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
// select DLLs in Everything
ProgramNode evNode = root.getChild("Everything");
visitNode(evNode);
ProgramNode dllsNode = evNode.getChild("DLLs");
visitNode(dllsNode);
setSelectionPath(dllsNode.getTreePath());
setSelectionPath(dllsNode);
performAction(pasteAction, true);
program.flushEvents();
performAction(pasteAction);
// first occurrence of DLLs should have icon for descendant in view
ProgramNode[] nodes = findNodes("DLLs");
@ -1012,15 +990,14 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
setViewPaths(new TreePath[] { dataNode.getTreePath(), debugNode.getTreePath() });
assertTrue(plugin.getView().hasSameAddresses(set));
setSelectionPath(debugNode.getTreePath());
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
setSelectionPath(debugNode);
performAction(cutAction);
// paste to an expanded folder not in the view
ProgramNode subrNode = root.getChild("Subroutines");
expandNode(subrNode);
setSelectionPath(subrNode.getTreePath());
performAction(pasteAction, true);
program.flushEvents();
setSelectionPath(subrNode);
performAction(pasteAction);
assertTrue(plugin.getView().hasSameAddresses(set));
}
@ -1032,31 +1009,30 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
// The pasted fragment's code units should not be in the view
ProgramNode dataNode = root.getChild(".data");
ProgramNode debugNode = root.getChild(".debug_data");
setViewPaths(new TreePath[] { dataNode.getTreePath(), debugNode.getTreePath() });
setViewPaths(dataNode, debugNode);
setSelectionPath(debugNode.getTreePath());
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
setSelectionPath(debugNode);
performAction(cutAction);
// paste onto another fragment that is not in the view
ProgramNode funcNode = root.getChild("Functions");
visitNode(funcNode);
ProgramNode sscanfNode = funcNode.getChild("sscanf");
setSelectionPath(sscanfNode.getTreePath());
performAction(pasteAction, true);
program.flushEvents();
setSelectionPath(sscanfNode);
performAction(pasteAction);
assertTrue(plugin.getView().hasSameAddresses(dataNode.getFragment()));
}
@Test
public void testCutFrag2FragInView() throws Exception {
// cut a fragment that is not in the view and paste it onto a
// cut a fragment that is not in the view and paste it onto a
// fragment that is in the view.
// The pasted fragment's code units should show up in the view
ProgramNode dataNode = root.getChild(".data");
ProgramNode debugNode = root.getChild(".debug_data");
setViewPaths(new TreePath[] { dataNode.getTreePath(), debugNode.getTreePath() });
setViewPaths(dataNode, debugNode);
ProgramNode subrNode = root.getChild("Subroutines");
visitNode(subrNode);
@ -1064,14 +1040,13 @@ public class ProgramTreePlugin2Test extends AbstractProgramTreePluginTest {
AddressSet set = new AddressSet();
set.add(node.getFragment());
// cut first frag in Subroutines
setSelectionPath(node.getTreePath());
runSwing(() -> cutAction.actionPerformed(new ActionContext()));
// cut first fragment in Subroutines
setSelectionPath(node);
performAction(cutAction);
// paste at the debug node
setSelectionPath(debugNode.getTreePath());
performAction(pasteAction, true);
program.flushEvents();
setSelectionPath(debugNode);
performAction(pasteAction);
assertTrue(plugin.getView().contains(set));
}

View file

@ -23,7 +23,6 @@ import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.JLabel;
import javax.swing.tree.TreePath;
import org.junit.*;
@ -107,7 +106,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
@After
public void tearDown() throws Exception {
waitForPostedSwingRunnables();
waitForSwing();
env.release(program);
env.dispose();
}
@ -123,13 +122,13 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// put .text in the view
ProgramNode textNode = root.getChild(".text");
setViewPaths(new TreePath[] { textNode.getTreePath() });
setViewPaths(textNode);
AddressSet set = plugin.getView();
ProgramNode subrNode = root.getChild("Subroutines");
visitNode(subrNode);
ProgramNode node = subrNode.getChild("01004a15");
setSelectionPath(node.getTreePath());
setSelectionPath(node);
ProgramNode funcNode = root.getChild("Functions");
visitNode(funcNode);
@ -164,76 +163,6 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
}
private void dragNodes_Move(ProgramNode node, List<ProgramNode> list) throws Exception {
dragNodes(node, list, DnDConstants.ACTION_MOVE);
}
private void dragNodes_Copy(ProgramNode node, List<ProgramNode> list) throws Exception {
dragNodes(node, list, DnDConstants.ACTION_COPY);
}
private void dragNodes(ProgramNode node, List<ProgramNode> list, int dropAction)
throws Exception {
AtomicReference<Exception> ref = new AtomicReference<>();
runSwing(() -> {
try {
tree.processDropRequest(node, list, TreeTransferable.localTreeNodeFlavor,
dropAction);
}
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
ref.set(e);
}
});
Exception exception = ref.get();
if (exception != null) {
throw exception;
}
program.flushEvents();
}
private void dropSelectionOnTree(ProgramNode node, SelectionTransferData data)
throws Exception {
AtomicReference<Exception> ref = new AtomicReference<>();
runSwing(() -> {
try {
tree.processDropRequest(node, data,
SelectionTransferable.localProgramSelectionFlavor, DnDConstants.ACTION_MOVE);
}
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
ref.set(e);
}
});
Exception exception = ref.get();
if (exception != null) {
throw exception;
}
program.flushEvents();
}
private void moveNode(ProgramNode to, ProgramNode toMove) throws Exception {
AtomicReference<Exception> ref = new AtomicReference<>();
runSwing(() -> {
try {
dndManager.add(to, new ProgramNode[] { toMove }, DnDConstants.ACTION_MOVE, 1);
}
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
ref.set(e);
}
});
Exception exception = ref.get();
if (exception != null) {
throw exception;
}
program.flushEvents();
}
@Test
public void testDnDFrag2FragInView() throws Exception {
// drag a fragment in the view onto another fragment not in the view
@ -242,7 +171,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode dataNode = root.getChild(".data");
ProgramNode debugNode = root.getChild(".debug_data");
setViewPaths(new TreePath[] { dataNode.getTreePath(), debugNode.getTreePath() });
setViewPaths(dataNode, debugNode);
AddressSet set = new AddressSet();
set.add(dataNode.getFragment());
set.add(debugNode.getFragment());
@ -251,7 +180,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
visitNode(subrNode);
ProgramNode node = subrNode.getChild("01004a15");
// drop target is 01004a15
setSelectionPath(node.getTreePath());
setSelectionPath(node);
AddressSet fragSet = new AddressSet(debugNode.getFragment());
ArrayList<ProgramNode> list = new ArrayList<ProgramNode>();
@ -262,7 +191,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
expandNode(root);
assertNull(listing.getFragment("Main Tree", ".debug_data"));
assertTrue(!plugin.getView().contains(fragSet));
assertFalse(plugin.getView().contains(fragSet));
assertEquals(0, findNodes(".debug_data").length);
@ -274,7 +203,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
redo();
expandNode(root);
assertNull(listing.getFragment("Main Tree", ".debug_data"));
assertTrue(!plugin.getView().contains(fragSet));
assertFalse(plugin.getView().contains(fragSet));
assertEquals(0, findNodes(".debug_data").length);
}
@ -290,7 +219,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode subrNode = root.getChild("Subroutines");
visitNode(subrNode);
setSelectionPath(subrNode.getTreePath());
setSelectionPath(subrNode);
dragNodes_Move(subrNode, Arrays.asList(dataNode));
@ -320,7 +249,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode extNode = root.getChild("Not Real Blocks");
// drag functions to external references
setSelectionPath(extNode.getTreePath());
setSelectionPath(extNode);
dragNodes_Move(extNode, Arrays.asList(funcNode));
@ -335,9 +264,8 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
break;
}
}
if (!found) {
Assert.fail("Did not find new parent of Functions");
}
assertTrue("Did not find new parent of Functions", found);
}
@Test
@ -358,13 +286,13 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
m.add(listing.getModule("Main Tree", "Functions"));
program.endTransaction(transactionID, true);
set.add(m.getAddressSet());
program.flushEvents();
waitForProgram(program);
expandNode(root);
ProgramNode testNode = root.getChild("Test");
setSelectionPath(testNode.getTreePath());
setSelectionPath(testNode);
ProgramNode stringsNode = root.getChild("Strings");
visitNode(stringsNode);
ProgramNode cNode = stringsNode.getChild("L");
@ -376,8 +304,6 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode tgtNode = fnode;
dragNodes_Move(tgtNode, Arrays.asList(n));
waitForSwing();
root = (ProgramNode) tree.getModel().getRoot();
// reacquire nodes
expandNode(root);
@ -406,7 +332,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
visitNode(cNode);
fnode = cNode.getChild("testl");
assertTrue(!fnode.getFragment().contains(set));
assertFalse(fnode.getFragment().contains(set));
expandNode(root);
testNode = root.getChild("Test");
assertNotNull(testNode);
@ -445,8 +371,8 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
copyFolderOrFragment("DLLs", "Everything");
ProgramNode dataNode = root.getChild(".data");
setSelectionPath(dataNode.getTreePath());
setViewPaths(new TreePath[] { dataNode.getTreePath() });
setSelectionPath(dataNode);
setViewPaths(dataNode);
// drag .data to DLLs
@ -455,7 +381,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
visitNode(evNode);
ProgramNode dllsNode = evNode.getChild("DLLs");
visitNode(dllsNode);
setSelectionPath(dllsNode.getTreePath());
setSelectionPath(dllsNode);
ProgramNode dragNode = dataNode;
dragNodes_Move(dllsNode, Arrays.asList(dragNode));
@ -485,7 +411,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode debugNode = root.getChild(".debug_data");
AddressSet set = new AddressSet(debugNode.getFragment());
setViewPaths(new TreePath[] { dataNode.getTreePath(), debugNode.getTreePath() });
setViewPaths(dataNode, debugNode);
ProgramNode subrNode = root.getChild("Subroutines");
visitNode(subrNode);
@ -512,7 +438,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// verify that the destination fragment contains the dragged
// code units
ProgramNode dataNode = root.getChild(".data");
setViewPaths(new TreePath[] { dataNode.getTreePath() });
setViewPaths(dataNode);
AddressSet set = new AddressSet();
set.addRange(getAddr(0x01002a9b), getAddr(0x01002aad));
@ -535,7 +461,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// verify that the source fragment is removed from the program
ProgramNode dataNode = root.getChild(".data");
setViewPaths(new TreePath[] { dataNode.getTreePath() });
setViewPaths(dataNode);
ProgramNode debugNode = root.getChild(".debug_data");
@ -565,7 +491,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode dataNode = root.getChild(".data");
ProgramNode debugNode = root.getChild(".debug_data");
setViewPaths(new TreePath[] { dataNode.getTreePath(), debugNode.getTreePath() });
setViewPaths(dataNode, debugNode);
AddressSet origSet = plugin.getView();
AddressSet set = new AddressSet();
@ -617,24 +543,21 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode textNode = root.getChild(".text");
ProgramNode debugNode = root.getChild(".debug_data");
assertTrue(!dndManager.isDropSiteOk(debugNode, new ProgramNode[] { textNode },
DnDConstants.ACTION_COPY, 0));
assertDropSiteInvalid(debugNode, textNode);
}
@Test
public void testDnDCopyFrag2Folder() throws Exception {
// drag/copy a fragment onto a folder that does not contain
//this fragment.
// Verify that all occurrences of the dest folder are updated with
// the new child.
// drag/copy a fragment onto a folder that does not contain this fragment.
// Verify that all occurrences of the dest folder are updated with the new child.
// Verify that the original parent folder remains intact.
ProgramNode textNode = root.getChild(".text");
setSelectionPath(textNode.getTreePath());
setSelectionPath(textNode);
ProgramNode dllsNode = root.getChild("DLLs");
int origCount = dllsNode.getChildCount();
setSelectionPath(dllsNode.getTreePath());
setSelectionPath(dllsNode);
dragNodes_Copy(dllsNode, Arrays.asList(textNode));
@ -666,8 +589,8 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode debugNode = root.getChild(".debug_data");
ProgramNode nrbNode = root.getChild("Not Real Blocks");
assertTrue(!dndManager.isDropSiteOk(nrbNode, new ProgramNode[] { debugNode },
DnDConstants.ACTION_COPY, 0));
assertDropSiteInvalid(nrbNode, debugNode);
}
@Test
@ -682,7 +605,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode destNode = root.getChild("DLLs");
int childCount = destNode.getChildCount();
setSelectionPath(dragNode.getTreePath());
setSelectionPath(dragNode);
// drag/copy Functions to DLLs
ProgramNode tgtNode = destNode;
@ -714,8 +637,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// Verify that there is no valid drop target.
ProgramNode subrNode = root.getChild("Subroutines");
ProgramNode evNode = root.getChild("Everything");
assertTrue(!dndManager.isDropSiteOk(evNode, new ProgramNode[] { subrNode },
DnDConstants.ACTION_COPY, 0));
assertDropSiteInvalid(evNode, subrNode);
}
@Test
@ -731,11 +653,11 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// Strings, L are expanded
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// drag/copy Strings to Functions
ProgramNode funcNode = root.getChild("Functions");
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
dragNodes_Copy(funcNode, Arrays.asList(stringsNode));
@ -759,12 +681,12 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// Strings, L are expanded
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// paste at Functions
ProgramNode funcNode = root.getChild("Functions");
collapsePath(funcNode.getTreePath());
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
// drag/copy Strings to Functions
dragNodes_Copy(funcNode, Arrays.asList(stringsNode));
@ -785,12 +707,12 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
collapsePath(stringsNode.getTreePath());
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// drag/copy Strings to Functions
ProgramNode funcNode = root.getChild("Functions");
expandPath(funcNode.getTreePath());
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
dragNodes_Copy(funcNode, Arrays.asList(stringsNode));
@ -810,13 +732,13 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
collapsePath(stringsNode.getTreePath());
// select Strings
setSelectionPath(stringsNode.getTreePath());
setSelectionPath(stringsNode);
// drag/copy Strings to Functions
ProgramNode funcNode = root.getChild("Functions");
visitNode(funcNode);
collapsePath(funcNode.getTreePath());
setSelectionPath(funcNode.getTreePath());
setSelectionPath(funcNode);
dragNodes_Move(funcNode, Arrays.asList(stringsNode));
@ -830,10 +752,10 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// verify that the view is not affected.
ProgramNode funcNode = root.getChild("Functions");
// set the view to Functions
setViewPaths(new TreePath[] { funcNode.getTreePath() });
setViewPaths(funcNode);
ProgramNode child = funcNode.getChild("doStuff");
setSelectionPath(child.getTreePath());
setSelectionPath(child);
ProgramNode subrNode = root.getChild("Subroutines");
@ -858,8 +780,8 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode funcNode = root.getChild("Functions");
// set the view to Functions
setSelectionPath(funcNode.getTreePath());
setViewPaths(new TreePath[] { funcNode.getTreePath() });
setSelectionPath(funcNode);
setViewPaths(funcNode);
ProgramNode subrNode = root.getChild("Subroutines");
@ -884,13 +806,13 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode funcNode = root.getChild("Functions");
// set the view to Functions
setViewPaths(new TreePath[] { funcNode.getTreePath() });
setViewPaths(funcNode);
AddressSetView origSet = funcNode.getModule().getAddressSet();
// select Subroutines (not in the view)
ProgramNode subrNode = root.getChild("Subroutines");
setSelectionPath(subrNode.getTreePath());
setSelectionPath(subrNode);
dragNodes_Move(funcNode, Arrays.asList(subrNode));
@ -913,7 +835,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag "L" and place it after "CC"
ProgramNode lnode = stringsNode.getChild("L");
ProgramNode cnode = stringsNode.getChild("CC");
setSelectionPath(lnode.getTreePath());
setSelectionPath(lnode);
moveNode(cnode, lnode);
@ -949,19 +871,13 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag "S" and place it after "CC"
ProgramNode snode = stringsNode.getChild("S");
ProgramNode cnode = stringsNode.getChild("CC");
setSelectionPath(snode.getTreePath());
setSelectionPath(snode);
runSwing(() -> {
try {
// place S after CC
dndManager.add(cnode, new ProgramNode[] { snode }, DnDConstants.ACTION_MOVE, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
runSwingWithException(() -> {
dndManager.add(cnode, new ProgramNode[] { snode }, DnDConstants.ACTION_MOVE, 1);
});
waitForProgram(program);
program.flushEvents();
String[] names = new String[] { "CC", "S", "G", "L" };
for (int i = 0; i < names.length; i++) {
assertEquals(names[i], stringsNode.getChildAt(i).toString());
@ -993,19 +909,13 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag "USER32.DLL" and place it above "ADVAPI32.DLL"
ProgramNode wnode = dllsNode.getChild("USER32.DLL");
ProgramNode anode = dllsNode.getChild("ADVAPI32.DLL");
setSelectionPath(wnode.getTreePath());
setSelectionPath(wnode);
runSwing(() -> {
try {
// place USER32.DLL above ADVAPI32.DLL
dndManager.add(anode, new ProgramNode[] { wnode }, DnDConstants.ACTION_MOVE, -1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
runSwingWithException(() -> {
dndManager.add(anode, new ProgramNode[] { wnode }, DnDConstants.ACTION_MOVE, -1);
});
waitForProgram(program);
program.flushEvents();
assertEquals("USER32.DLL", dllsNode.getFirstChild().toString());
ProgramNode node = dllsNode.getChild("USER32.DLL");
@ -1032,22 +942,15 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode debugNode = root.getChild(".debug_data");
ProgramNode cnode = stringsNode.getChild("CC");
setSelectionPath(debugNode.getTreePath());
setSelectionPath(debugNode);
// drag .debug_data to Strings and place it above C
runSwing(() -> {
try {
// place .debug_data above C
dndManager.add(cnode, new ProgramNode[] { debugNode }, DnDConstants.ACTION_MOVE,
-1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
runSwingWithException(() -> {
dndManager.add(cnode, new ProgramNode[] { debugNode }, DnDConstants.ACTION_MOVE, -1);
});
waitForProgram(program);
program.flushEvents();
// verify that .debug_data is the first child in Strings
// .debug_data should remain selected
// .debug_data should be removed from Not Real Blocks
@ -1076,22 +979,17 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// expand DLLs
ProgramNode dllsNode = root.getChild("DLLs");
expandNode(dllsNode);
setSelectionPath(dllsNode.getTreePath());
setSelectionPath(dllsNode);
ProgramNode lnode = stringsNode.getChild("L");
collapseNode(lnode);
// drag DLLs below L in Strings
runSwing(() -> {
try {
// place DLLs below L
dndManager.add(lnode, new ProgramNode[] { dllsNode }, DnDConstants.ACTION_MOVE, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
// place DLLs below L
dndManager.add(lnode, new ProgramNode[] { dllsNode }, DnDConstants.ACTION_MOVE, 1);
});
waitForProgram(program);
// verify that DLLs is the last child in Strings
// verify that DLLs is still expanded
@ -1128,17 +1026,12 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag Strings between 01004a15 and 010030d8 in Subroutines
ProgramNode node = subrNode.getChild("01004a15");
ProgramNode strNode = stringsNode;
runSwing(() -> {
try {
// place Strings below 01004a15 in Subroutines
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_MOVE, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
// place DLLs below L
runSwingWithException(() -> {
// place Strings below 01004a15 in Subroutines
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_MOVE, 1);
});
program.flushEvents();
waitForProgram(program);
// verify that Strings is expanded and is the 3rd child in Subroutines
// Verify that Strings remains selected
@ -1173,17 +1066,12 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag Strings between 01004a15 and 010030d8 in Subroutines
ProgramNode node = subrNode.getChild("01004a15");
ProgramNode strNode = stringsNode;
runSwing(() -> {
try {
// place Strings above 01004a15 in Subroutines
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_MOVE, -1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
// place Strings above 01004a15 in Subroutines
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_MOVE, -1);
});
waitForProgram(program);
// verify that Strings is expanded and is the 2nd child in Subroutines
// Verify that Strings remains selected
@ -1218,16 +1106,11 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag 010030d8 from Subroutines to Everything and place after
// Everything
runSwing(() -> {
try {
dndManager.add(evNode, new ProgramNode[] { node }, DnDConstants.ACTION_MOVE, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
dndManager.add(evNode, new ProgramNode[] { node }, DnDConstants.ACTION_MOVE, 1);
});
waitForProgram(program);
// verify that 010030d8 is the first child in Everything
assertEquals("010030d8", evNode.getFirstChild().toString());
@ -1238,16 +1121,11 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// from Subroutines drag 01004a15 below Everything
ProgramNode node2 = subrNode.getChild("01004a15");
runSwing(() -> {
try {
dndManager.add(evNode, new ProgramNode[] { node2 }, DnDConstants.ACTION_MOVE, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
dndManager.add(evNode, new ProgramNode[] { node2 }, DnDConstants.ACTION_MOVE, 1);
});
waitForProgram(program);
// verify that 01004a15 is moved to the root node and placed
// after Everything
@ -1269,16 +1147,11 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag/copy 010030d8 from Subroutines to Everything and place after
// Everything
runSwing(() -> {
try {
dndManager.add(evNode, new ProgramNode[] { node }, DnDConstants.ACTION_COPY, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
dndManager.add(evNode, new ProgramNode[] { node }, DnDConstants.ACTION_COPY, 1);
});
waitForProgram(program);
// verify that 010030d8 is the first child in Everything
assertEquals("010030d8", evNode.getFirstChild().toString());
@ -1289,14 +1162,11 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// from Subroutines drag 01004a15 below Everything
ProgramNode node2 = subrNode.getChild("01004a15");
runSwing(() -> {
try {
dndManager.add(evNode, new ProgramNode[] { node2 }, DnDConstants.ACTION_COPY, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
runSwingWithException(() -> {
dndManager.add(evNode, new ProgramNode[] { node2 }, DnDConstants.ACTION_COPY, 1);
});
waitForProgram(program);
// verify that 01004a15 is copied to the root node and placed
// after Everything
@ -1313,22 +1183,16 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// expand DLLs
ProgramNode dllsNode = root.getChild("DLLs");
expandNode(dllsNode);
setSelectionPath(dllsNode.getTreePath());
setSelectionPath(dllsNode);
ProgramNode lnode = stringsNode.getChild("L");
collapseNode(lnode);
// drag/copy DLLs below L in Strings
runSwing(() -> {
try {
// place DLLs below L
dndManager.add(lnode, new ProgramNode[] { dllsNode }, DnDConstants.ACTION_COPY, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
dndManager.add(lnode, new ProgramNode[] { dllsNode }, DnDConstants.ACTION_COPY, 1);
});
waitForProgram(program);
// verify that DLLs is the last child in Strings
// verify that DLLs is still expanded
@ -1365,17 +1229,11 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag/copy Strings between 01004a15 and 010030d8 in Subroutines
ProgramNode node = subrNode.getChild("01004a15");
ProgramNode strNode = stringsNode;
runSwing(() -> {
try {
// place Strings above 01004a15 in Subroutines
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_COPY, -1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_COPY, -1);
});
waitForProgram(program);
// verify that Strings is expanded and is the 2nd child in Subroutines
// Verify that Strings remains selected
@ -1410,17 +1268,11 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
// drag/copy Strings between 01004a15 and 010030d8 in Subroutines
ProgramNode node = subrNode.getChild("01004a15");
ProgramNode strNode = stringsNode;
runSwing(() -> {
try {
// place Strings below 01004a15 in Subroutines
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_COPY, 1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
});
program.flushEvents();
runSwingWithException(() -> {
dndManager.add(node, new ProgramNode[] { strNode }, DnDConstants.ACTION_COPY, 1);
});
waitForProgram(program);
// verify that Strings is expanded and is the 3rd child in Subroutines
// Verify that Strings remains selected
@ -1454,22 +1306,16 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode debugNode = root.getChild(".debug_data");
ProgramNode cnode = stringsNode.getChild("CC");
setSelectionPath(debugNode.getTreePath());
setSelectionPath(debugNode);
// drag/copy .debug_data to Strings and place it above CC
runSwing(() -> {
try {
// place .debug_data above CC
dndManager.add(cnode, new ProgramNode[] { debugNode }, DnDConstants.ACTION_COPY,
-1);
}
catch (Exception e) {
Assert.fail(e.getMessage());
}
runSwingWithException(() -> {
// place .debug_data above CC
dndManager.add(cnode, new ProgramNode[] { debugNode }, DnDConstants.ACTION_COPY, -1);
});
waitForProgram(program);
program.flushEvents();
// verify that .debug_data is the first child in Strings
// .debug_data should remain selected
// .debug_data should not be removed from Not Real Blocks
@ -1495,8 +1341,7 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode debugNode = root.getChild(".debug_data");
ProgramNode nrbNode = root.getChild("Not Real Blocks");
assertTrue(!dndManager.isDropSiteOk(nrbNode, new ProgramNode[] { debugNode },
DnDConstants.ACTION_COPY, 1));
assertDropSiteInvalid(nrbNode, debugNode);
}
@Test
@ -1504,8 +1349,12 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
ProgramNode debugNode = root.getChild(".debug_data");
ProgramNode textNode = root.getChild(".text");
assertTrue(!dndManager.isDropSiteOk(textNode, new ProgramNode[] { debugNode },
DnDConstants.ACTION_COPY, 1));
assertDropSiteInvalid(textNode, debugNode);
}
private void assertDropSiteInvalid(ProgramNode destinationNode, ProgramNode... dropNodes) {
assertFalse(
dndManager.isDropSiteOk(destinationNode, dropNodes, DnDConstants.ACTION_COPY, 1));
}
private DockingActionIf getAction(String name) {
@ -1518,18 +1367,88 @@ public class ProgramTreePlugin3Test extends AbstractProgramTreePluginTest {
return null;// cannot get here
}
private void dragNodes_Move(ProgramNode node, List<ProgramNode> list) throws Exception {
dragNodes(node, list, DnDConstants.ACTION_MOVE);
}
private void dragNodes_Copy(ProgramNode node, List<ProgramNode> list) throws Exception {
dragNodes(node, list, DnDConstants.ACTION_COPY);
}
private void dragNodes(ProgramNode node, List<ProgramNode> list, int dropAction)
throws Exception {
AtomicReference<Exception> ref = new AtomicReference<>();
runSwing(() -> {
try {
tree.processDropRequest(node, list, TreeTransferable.localTreeNodeFlavor,
dropAction);
}
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
ref.set(e);
}
});
Exception exception = ref.get();
if (exception != null) {
throw exception;
}
waitForProgram(program);
}
private void dropSelectionOnTree(ProgramNode node, SelectionTransferData data)
throws Exception {
AtomicReference<Exception> ref = new AtomicReference<>();
runSwing(() -> {
try {
tree.processDropRequest(node, data,
SelectionTransferable.localProgramSelectionFlavor, DnDConstants.ACTION_MOVE);
}
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
ref.set(e);
}
});
Exception exception = ref.get();
if (exception != null) {
throw exception;
}
waitForProgram(program);
}
private void moveNode(ProgramNode to, ProgramNode toMove) throws Exception {
AtomicReference<Exception> ref = new AtomicReference<>();
runSwing(() -> {
try {
dndManager.add(to, new ProgramNode[] { toMove }, DnDConstants.ACTION_MOVE, 1);
}
catch (NotFoundException | CircularDependencyException | DuplicateGroupException e) {
ref.set(e);
}
});
Exception exception = ref.get();
if (exception != null) {
throw exception;
}
waitForProgram(program);
}
private void copyFolderOrFragment(String src, String dst) {
// copy a folder that is in the view to another folder that is not in the view
ProgramNode node = root.getChild(src);
setSelectionPath(node.getTreePath());
setViewPaths(new TreePath[] { node.getTreePath() });
performAction(copyAction, true);
setSelectionPath(node);
setViewPaths(node);
performAction(copyAction);
ProgramNode everythingNode = root.getChild(dst);
setSelectionPath(everythingNode.getTreePath());
setSelectionPath(everythingNode);
assertTrue(pasteAction.isEnabled());
performAction(pasteAction, true);
performAction(pasteAction);
}
}

View file

@ -15,7 +15,7 @@
*/
package generic.test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
import java.awt.*;
import java.awt.event.*;
@ -43,6 +43,7 @@ import org.junit.rules.*;
import org.junit.runner.Description;
import generic.jar.ResourceFile;
import generic.test.rule.Repeated;
import generic.test.rule.RepeatedTestRule;
import generic.util.WindowUtilities;
import ghidra.GhidraTestApplicationLayout;
@ -116,7 +117,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* This rule handles the {@link Repeated} annotation
*
*
* <p>
* During batch mode, this rule should never be needed. This rule is included here as a
* convenience, in case a developer wants to use the {@link Repeated} annotation to diagnose a
@ -169,7 +170,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* A method to update any {@link ApplicationLayout} values
*
*
* @param layout the layout to initialize
*/
protected void initializeLayout(ApplicationLayout layout) {
@ -223,7 +224,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Determine if test failure occur (for use within tear down methods)
*
*
* @return true if test failure detected
*/
protected boolean hasTestFailed() {
@ -234,7 +235,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* A callback for subclasses when a test has failed. This will be called
* <b>after</b> <code>tearDown()</code>. This means that any diagnostics will have to
* take into account items that have already been disposed.
*
*
* @param e the exception that happened when the test failed
*/
protected void testFailed(Throwable e) {
@ -264,8 +265,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
public static Set<Window> getAllWindows() {
Set<Window> set = new HashSet<>();
Frame sharedOwnerFrame = (Frame) AppContext.getAppContext()
.get(
new StringBuffer("SwingUtilities.sharedOwnerFrame"));
.get(new StringBuffer("SwingUtilities.sharedOwnerFrame"));
if (sharedOwnerFrame != null) {
set.addAll(getAllWindows(sharedOwnerFrame));
}
@ -306,7 +306,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Load a text resource file into an ArrayList. Each line of the file is
* stored as an item in the list.
*
*
* @param cls class where resource exists
* @param name resource filename
* @return list of lines contained in file
@ -403,7 +403,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Returns the data directory containing test programs and data
*
*
* @return the data directory containing test programs and data
*/
public static File getTestDataDirectory() {
@ -506,7 +506,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* Get the first field object contained within object ownerInstance which
* has the type classType. This method is only really useful if it is known
* that only a single field of classType exists within the ownerInstance.
*
*
* @param <T> the type
* @param classType the class type of the desired field
* @param ownerInstance the object instance that owns the field
@ -647,7 +647,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* Finds the button with the indicated TEXT that is a sub-component of the
* indicated container, and then programmatically presses the button. <BR>
* The following is a sample JUnit test use:
*
*
* <PRE>
* env.showTool();
* OptionDialog dialog = (OptionDialog) env.waitForDialog(OptionDialog.class, 1000);
@ -667,7 +667,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Finds the button with the indicated TEXT that is a sub-component of the
* indicated container, and then programmatically presses the button.
*
*
* @param container the container to search. (Typically a dialog.)
* @param buttonText the text on the desired JButton.
* @param waitForCompletion if true wait for action to complete before
@ -695,7 +695,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Finds the button with the indicated NAME that is a subcomponent of the
* indicated container, and then programmatically presses the button.
*
*
* @param container the container to search. (Typically a dialog)
* @param buttonName the name on the desired AbstractButton (see
* Component.setName())
@ -707,7 +707,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Finds the button with the indicated NAME that is a subcomponent of the
* indicated container, and then programmatically presses the button.
*
*
* @param container the container to search. (Typically a dialog.)
* @param buttonName the name on the desired AbstractButton (see
* Component.setName()).
@ -733,7 +733,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Programmatically presses the indicated button.
*
*
* @param button the button
*/
public static void pressButton(AbstractButton button) {
@ -745,7 +745,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Programmatically presses the indicated button.
*
*
* @param button the button
* @param waitForCompletion if true wait for action to complete before
* returning, otherwise schedule action to be performed and
@ -854,7 +854,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Searches the subcomponents of the the given container and returns the
* JButton that has the specified text.
*
*
* @param container the container to search
* @param text the button text
* @return the JButton, or null the button was not found
@ -954,7 +954,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Simulates click the mouse button.
*
*
* @param comp the component to click on.
* @param button the mouse button (1, 2, or 3)
* @param x the x coordinate of the click location
@ -982,7 +982,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Simulates click the mouse button.
*
*
* @param comp the component to click on.
* @param button the mouse button (1, 2, or 3)
* @param x the x coordinate of the click location
@ -998,7 +998,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Simulates a mouse drag action
*
*
* @param comp the component to drag on.
* @param button the mouse button (1, 2, or 3)
* @param startX the x coordinate of the start drag location
@ -1022,7 +1022,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Fire a mouse moved event for the given component.
*
*
* @param comp source of the event.
* @param x x position relative to the component
* @param y y position relative to the component
@ -1121,9 +1121,9 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Run the given code snippet on the Swing thread later, not blocking the current thread. Use
* this if the code snippet causes a blocking operation.
*
*
* <P>This is a shortcut for <code>runSwing(r, false);</code>.
*
*
* @param r the runnable code snippet
*/
public void runSwingLater(Runnable r) {
@ -1133,7 +1133,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Call this version of {@link #runSwing(Runnable)} when you expect your runnable <b>may</b>
* throw exceptions
*
*
* @param callback the runnable code snippet to call
* @throws Exception any exception that is thrown on the Swing thread
*/
@ -1360,7 +1360,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Clicks a range of items in a list (simulates holding SHIFT and selecting
* each item in the range in-turn)
*
*
* @param list the list to select from
* @param row the initial index
* @param count the number of rows to select
@ -1378,7 +1378,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Clicks a range of items in a table (simulates holding SHIFT and selecting
* each item in the range)
*
*
* @param table the table to select
* @param row the starting row index
* @param count the number of rows to select
@ -1411,7 +1411,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Gets the rendered value for the specified table cell. The actual value at the cell may
* not be a String. This method will get the String display value, as created by the table.
*
*
* @param table the table to query
* @param row the row to query
* @param column the column to query
@ -1459,7 +1459,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* Note: This method affects the expansion state of the tree. It will expand
* nodes starting at the root until a match is found or all of the tree is
* checked.
*
*
* @param tree the tree
* @param text the tree node's text
* @return the tree path
@ -1473,7 +1473,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Performs a depth first search for the named tree node.
*
*
* @param tree the tree to search
* @param startTreePath path indicating node to begin searching from in the
* tree
@ -1505,7 +1505,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Returns a string which is a printout of a stack trace for each thread
* running in the current JVM
*
*
* @return the stack trace string
*/
public static String createStackTraceForAllThreads() {
@ -1515,7 +1515,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
/**
* Prints the contents of the given collection by way of the
* {@link Object#toString()} method.
*
*
* @param collection The contents of which to print
* @return A string representation of the given collection
*/
@ -1841,7 +1841,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* {@link Files#createTempDirectory(Path, String, java.nio.file.attribute.FileAttribute...)}.
* Any left-over test directories will be cleaned-up before creating the new
* directory.
*
*
* <p>
* Note: you should not call this method multiple times, as each call will
* cleanup the previously created directories.
@ -1875,7 +1875,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* Creates a file path with a filename that is under the system temp
* directory. The path returned will not point to an existing file. The
* suffix of the file will be <code>.tmp</code>.
*
*
* @param name the filename
* @return a new file path
* @throws IOException if there is any problem ensuring that the created
@ -1892,7 +1892,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* directory. The path returned will not point to an existing file. This
* method is the same as {@link #createTempFilePath(String)}, except that
* you must provide the extension.
*
*
* @param name the filename
* @param extension the file extension
* @return a new file path
@ -1911,7 +1911,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* for the filename. This method calls {@link #createTempFile(String)},
* which will cleanup any pre-existing temp files whose name pattern matches
* this test name. This helps to avoid old temp files from accumulating.
*
*
* @return the new temp file
* @throws IOException if there is a problem creating the new file
*/
@ -1924,7 +1924,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* for the filename. This method calls {@link #createTempFile(String)},
* which will cleanup any pre-existing temp files whose name pattern matches
* this test name. This helps to avoid old temp files from accumulating.
*
*
* @param suffix the suffix to provide for the temp file
* @return the new temp file
* @throws IOException if there is a problem creating the new file