GP-65 - Error Dialog - updated the error dialog to accumulate errors

while it is open instead of repeatedly showing new dialogs
This commit is contained in:
dragonmacher 2020-08-20 17:37:44 -04:00
parent 4506acddf9
commit fc247aa499
44 changed files with 1784 additions and 1662 deletions

View file

@ -498,7 +498,7 @@ class AnalyzeAllOpenProgramsTask extends Task {
if (message != null && message.toLowerCase().startsWith("<html>")) {
JEditorPane editorPane = new JEditorPane();
editorPane.setEditorKit(new HTMLEditorKit());
editorPane.setName("MESSAGE-COMPONENT");
editorPane.setName(MESSAGE_COMPONENT_NAME);
editorPane.setText(message);
editorPane.setBackground(new GLabel().getBackground());

View file

@ -15,6 +15,10 @@
*/
package ghidra.app.plugin.core.datamgr.actions;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.tree.GTreeState;
import ghidra.app.plugin.core.datamgr.*;
import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
import ghidra.app.plugin.core.datamgr.tree.ArchiveNode;
@ -23,10 +27,6 @@ import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.SourceArchive;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.tree.GTreeState;
public class SyncRefreshAction extends DockingAction {
@ -92,7 +92,7 @@ public class SyncRefreshAction extends DockingAction {
getClass(),
plugin.getTool().getToolFrame(),
"Refresh Completed",
"Sync indicators refresh for " + dtm.getName() + " to archive \"" +
"Sync indicators have been refreshed between " + dtm.getName() + " and archive \"" +
sourceArchive.getName() + "\".");
tree.restoreTreeState(treeState);

View file

@ -24,7 +24,6 @@ import java.util.regex.Pattern;
import javax.swing.ImageIcon;
import docking.*;
import docking.action.DockingAction;
import docking.action.builder.ActionBuilder;
import docking.tool.ToolConstants;
import docking.widgets.fieldpanel.support.Highlight;
@ -96,8 +95,6 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
private static final String DESCRIPTION = "Search program text for string";
private final static int DEFAULT_SEARCH_LIMIT = 500;
private final static Highlight[] NO_HIGHLIGHTS = new Highlight[0];
private DockingAction searchAction;
private DockingAction searchAgainAction;
private boolean waitingForSearchAll;
private SearchTextDialog searchDialog;
@ -379,7 +376,7 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
private void createActions() {
String subGroup = getClass().getName();
searchAction = new ActionBuilder("Search Text", getName())
new ActionBuilder("Search Text", getName())
.menuPath("&Search", "Program &Text...")
.menuGroup("search", subGroup)
.keyBinding("ctrl shift E")
@ -393,7 +390,7 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
})
.buildAndInstall(tool);
searchAgainAction = new ActionBuilder("Repeat Text Search", getName())
new ActionBuilder("Repeat Text Search", getName())
.menuPath("&Search", "Repeat Text Search")
.menuGroup("search", subGroup)
.keyBinding("ctrl shift F3")

View file

@ -145,7 +145,7 @@ public abstract class AbstractMergeTest extends AbstractGhidraHeadedIntegrationT
List<Dialog> modals =
WindowUtilities.getOpenModalDialogsFor(mergeMgr.getMergeTool().getToolFrame());
Msg.debug(this, "Open modal dialog: ");
Msg.debug(this, "Open modal dialogs: ");
for (Dialog dialog : modals) {
capture(dialog);
}

View file

@ -25,7 +25,6 @@ import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.task.TaskMonitor;
import ghidra.util.task.TaskMonitorAdapter;
/**
* More data type merge tests.
@ -46,7 +45,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
// 2 components should get removed from CoolUnion
commit = true;
}
@ -119,7 +118,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
// 2 components should get removed from CoolUnion
commit = true;
}
@ -192,7 +191,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
// 2 components should get removed from CoolUnion
commit = true;
}
@ -573,7 +572,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -649,7 +648,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
// causes Bar to be marked as changed
commit = true;
}
@ -724,7 +723,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
// causes Bar to be marked as changed
commit = true;
}
@ -801,7 +800,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
Structure ms = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
"MyStruct");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
Structure s1 = new StructureDataType(
new CategoryPath("/Category1/Category2/Category5"), "s1", 0);
s1.add(ms);
@ -916,7 +915,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
int transactionID = program.startTransaction("test");
DataType dt = dtm.getDataType(new CategoryPath("/Category1/Category2"), "BF");
try {
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
}
finally {
program.endTransaction(transactionID, true);
@ -1260,7 +1259,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
// 2 components should get removed from CoolUnion
commit = true;
}
@ -1353,7 +1352,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
// 2 components should get removed from CoolUnion
commit = true;
}
@ -1436,10 +1435,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -1524,10 +1523,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -1613,10 +1612,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -1701,10 +1700,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -1795,10 +1794,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {
@ -1897,10 +1896,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
try {
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
dtm.remove(s, TaskMonitorAdapter.DUMMY);
dtm.remove(s, TaskMonitor.DUMMY);
DataType dt =
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
dtm.remove(dt, TaskMonitor.DUMMY);
commit = true;
}
finally {

View file

@ -755,8 +755,4 @@ public class StructureEditorProviderTest extends AbstractStructureEditorTest {
assertEquals("325", model.getLengthAsString());
}
private void runSwingLater(Runnable r) {
runSwing(r, false);
}
}

View file

@ -15,8 +15,7 @@
*/
package ghidra.app.plugin.core.datamgr.editor;
import static ghidra.app.plugin.core.datamgr.editor.EnumTableModel.NAME_COL;
import static ghidra.app.plugin.core.datamgr.editor.EnumTableModel.VALUE_COL;
import static ghidra.app.plugin.core.datamgr.editor.EnumTableModel.*;
import static org.junit.Assert.*;
import java.awt.*;
@ -42,7 +41,7 @@ import ghidra.program.model.data.Enum;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.EquateTable;
import ghidra.test.*;
import ghidra.util.task.TaskMonitorAdapter;
import ghidra.util.task.TaskMonitor;
/**
* Tests for editing an Enumerated data type.
@ -54,10 +53,6 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
private TestEnv env;
private DataTypeManagerPlugin plugin;
public EnumEditor1Test() {
super();
}
@Before
public void setUp() throws Exception {
env = new TestEnv();
@ -80,8 +75,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testEnumFields() throws Exception {
Category c = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category c = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Enum enumm = createEnum(c, "TestEnum", 1);
edit(enumm);
@ -133,8 +130,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testEnumSize1() throws Exception {
Category category = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category category = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Enum enumm = createEnum(category, "TestEnum", 1);
edit(enumm);
@ -183,8 +182,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testEnumSize1BadInput() throws Exception {
// test entering too large a value
Category category = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category category = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Enum enumm = createEnum(category, "TestEnum", 1);
edit(enumm);
@ -225,8 +226,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testEnumSize4BadInput() throws Exception {
Category category = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category category = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Enum enumm = createEnum(category, "MyTestEnum", 4);
edit(enumm);
@ -275,8 +278,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testBadInputForValue() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Enum enumm = createEnum(cat, "TestEnum", 1);
edit(enumm);
@ -303,8 +308,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testEditExistingEnum1() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 1);
@ -366,8 +373,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testValueForNewEntry() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0x10);
enumm.add("Green", 0x20);
@ -521,10 +530,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
removeCategory(enummDt);
OptionDialog dialog =
waitForDialogComponent(null, OptionDialog.class, DEFAULT_WINDOW_TIMEOUT);
assertNotNull(dialog);
pressButtonByText(dialog.getComponent(), "OK");
close(waitForErrorDialog());
}
@Test
@ -564,10 +570,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
replaceDataType(enummDt, newEnummDt);
OptionDialog dialog =
waitForDialogComponent(null, OptionDialog.class, DEFAULT_WINDOW_TIMEOUT);
assertNotNull(dialog);
pressButtonByText(dialog.getComponent(), "OK");
close(waitForErrorDialog());
}
@Test
@ -612,15 +615,12 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
DataTypeManager dtm = program.getDataTypeManager();
int transactionID = program.startTransaction("Test");
dtm.remove(enummDt, TaskMonitorAdapter.DUMMY_MONITOR);
dtm.remove(enummDt, TaskMonitor.DUMMY);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForSwing();
OptionDialog optionDialog =
waitForDialogComponent(null, OptionDialog.class, DEFAULT_WINDOW_TIMEOUT);
assertNotNull("Did not get informed of deleted enum", optionDialog);
pressButtonByText(optionDialog.getComponent(), "OK");
close(waitForErrorDialog());
}
@Test
@ -762,8 +762,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testChangeEnumSizeAndInStructure() throws Exception {
Category category = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category category = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Enum enumm = createEnum(category, "EnumX", 2);
int transactionID = program.startTransaction("Test");
@ -803,7 +805,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
assertEquals(intValue, 2);
runSwing(() -> {
sizeComboBox.setSelectedItem(new Integer(4));
sizeComboBox.setSelectedItem(4);
});
apply();
@ -831,8 +833,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testChangeEnumDescriptionEtcAndInStructure() throws Exception {
Category category = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category category = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Enum enumm = createEnum(category, "EnumX", 2);
int transactionID = program.startTransaction("Test");
@ -887,7 +891,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
runSwing(() -> {
nameField.setText("EnumY");
descField.setText("XYZ");
sizeComboBox.setSelectedItem(new Integer(4));
sizeComboBox.setSelectedItem(4);
table.editCellAt(1, NAME_COL);
@ -1026,7 +1030,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
try {
Category newCategory = dtm.createCategory(new CategoryPath("/Test/Category"));
category = dtm.getCategory(enummDt.getCategoryPath());
newCategory.moveCategory(category, TaskMonitorAdapter.DUMMY_MONITOR);
newCategory.moveCategory(category, TaskMonitor.DUMMY);
}
finally {
program.endTransaction(txID, true);
@ -1046,7 +1050,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
Category category = dtm.getCategory(enummDt.getCategoryPath());
Category parentCategory = category.getParent();
assertTrue("Did not remove category", parentCategory.removeCategory(category.getName(),
TaskMonitorAdapter.DUMMY_MONITOR));
TaskMonitor.DUMMY));
}
finally {
program.endTransaction(txID, true);
@ -1138,8 +1142,10 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
}
private Enum createRedGreenBlueEnum() {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 1);
@ -1274,7 +1280,7 @@ public class EnumEditor1Test extends AbstractGhidraHeadedIntegrationTest {
editValueInTable(0, "2");
// This IS the warning dialog
OptionDialog dialog = env.waitForDialogComponent(OptionDialog.class, 1000);
OptionDialog dialog = waitForDialogComponent(OptionDialog.class);
pressButtonByText(dialog, alsoRemove ? "Save and remove" : "Save");
waitForTasks();

View file

@ -24,8 +24,7 @@ import javax.swing.table.*;
import org.junit.*;
import docking.ActionContext;
import docking.ComponentProvider;
import docking.*;
import docking.action.DockingActionIf;
import docking.widgets.OptionDialog;
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
@ -69,8 +68,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testInsertRow() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 0x10);
@ -80,10 +81,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final Enum enumDt = (Enum) cat.addDataType(enumm, DataTypeConflictHandler.DEFAULT_HANDLER);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
SwingUtilities.invokeLater(() -> plugin.edit(enumDt));
waitForPostedSwingRunnables();
waitForSwing();
EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
final JTable table = panel.getTable();
@ -104,8 +105,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testSortColumns() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 0x10);
@ -115,10 +118,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final Enum enummDt = (Enum) cat.addDataType(enumm, DataTypeConflictHandler.DEFAULT_HANDLER);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
SwingUtilities.invokeLater(() -> plugin.edit(enummDt));
waitForPostedSwingRunnables();
waitForSwing();
EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
final JTable table = panel.getTable();
@ -128,7 +131,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
JTableHeader header = table.getTableHeader();
Rectangle rect = header.getHeaderRect(EnumTableModel.NAME_COL);
clickMouse(header, 1, rect.x, rect.y, 1, 0);
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("Blue", model.getValueAt(0, EnumTableModel.NAME_COL));
assertEquals("Green", model.getValueAt(1, EnumTableModel.NAME_COL));
@ -137,7 +140,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
// sort by Value
rect = header.getHeaderRect(EnumTableModel.VALUE_COL);
clickMouse(header, 1, rect.x, rect.y, 1, 0);
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("Red", model.getValueAt(0, EnumTableModel.NAME_COL));
assertEquals("Green", model.getValueAt(1, EnumTableModel.NAME_COL));
@ -146,8 +149,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testSortOrder() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 0x10);
@ -157,10 +162,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final Enum enummDt = (Enum) cat.addDataType(enumm, DataTypeConflictHandler.DEFAULT_HANDLER);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
SwingUtilities.invokeLater(() -> plugin.edit(enummDt));
waitForPostedSwingRunnables();
waitForSwing();
EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
final JTable table = panel.getTable();
@ -170,7 +175,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
JTableHeader header = table.getTableHeader();
Rectangle rect = header.getHeaderRect(EnumTableModel.VALUE_COL);
clickMouse(header, 1, rect.x, rect.y, 1, 0);
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("0x20", model.getValueAt(0, EnumTableModel.VALUE_COL));
assertEquals("0x10", model.getValueAt(1, EnumTableModel.VALUE_COL));
@ -179,10 +184,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
// sort by Name
rect = header.getHeaderRect(EnumTableModel.NAME_COL);
clickMouse(header, 1, rect.x, rect.y, 1, 0);
waitForPostedSwingRunnables();
waitForSwing();
// sort Descending
clickMouse(header, 1, rect.x, rect.y, 1, 0);
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("Red", model.getValueAt(0, EnumTableModel.NAME_COL));
assertEquals("Green", model.getValueAt(1, EnumTableModel.NAME_COL));
assertEquals("Blue", model.getValueAt(2, EnumTableModel.NAME_COL));
@ -190,8 +195,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testInsertRowByName() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 0x10);
@ -201,10 +208,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final Enum enummDt = (Enum) cat.addDataType(enumm, DataTypeConflictHandler.DEFAULT_HANDLER);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
SwingUtilities.invokeLater(() -> plugin.edit(enummDt));
waitForPostedSwingRunnables();
waitForSwing();
EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
final JTable table = panel.getTable();
@ -214,7 +221,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
JTableHeader header = table.getTableHeader();
Rectangle rect = header.getHeaderRect(EnumTableModel.NAME_COL);
clickMouse(header, 1, rect.x, rect.y, 1, 0);
waitForPostedSwingRunnables();
waitForSwing();
// insert "Cyan"
addEntry(table, model, "Cyan", 0x30);
@ -236,16 +243,16 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final DockingActionIf deleteAction = getAction(plugin, "Delete Enum Value");
assertTrue(deleteAction.isEnabled());
SwingUtilities.invokeAndWait(() -> deleteAction.actionPerformed(new ActionContext()));
waitForPostedSwingRunnables();
runSwing(() -> deleteAction.actionPerformed(new ActionContext()));
waitForSwing();
assertTrue(table.isRowSelected(3));
final DockingActionIf applyAction = getAction(plugin, "Apply Enum Changes");
assertTrue(applyAction.isEnabled());
SwingUtilities.invokeAndWait(() -> applyAction.actionPerformed(new ActionContext()));
runSwing(() -> applyAction.actionPerformed(new ActionContext()));
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(4, model.getRowCount());
assertEquals(4, enummDt.getCount());
@ -265,8 +272,8 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
for (int i = 0; i < count; i++) {
SwingUtilities.invokeAndWait(() -> deleteAction.actionPerformed(new ActionContext()));
waitForPostedSwingRunnables();
runSwing(() -> deleteAction.actionPerformed(new ActionContext()));
waitForSwing();
}
assertEquals(0, model.getRowCount());
// add an entry so the tear down works properly
@ -287,8 +294,8 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
for (int i = 0; i < count; i++) {
SwingUtilities.invokeAndWait(() -> deleteAction.actionPerformed(new ActionContext()));
waitForPostedSwingRunnables();
runSwing(() -> deleteAction.actionPerformed(new ActionContext()));
waitForSwing();
}
applyChanges(true);
Window w = windowForComponent(table);
@ -313,20 +320,20 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
for (int i = 0; i < count; i++) {
SwingUtilities.invokeAndWait(() -> deleteAction.actionPerformed(new ActionContext()));
waitForPostedSwingRunnables();
runSwing(() -> deleteAction.actionPerformed(new ActionContext()));
waitForSwing();
}
final ComponentProvider provider =
waitForComponentProvider(tool.getToolFrame(), EnumEditorProvider.class, 1500);
waitForComponentProvider(EnumEditorProvider.class);
assertNotNull(provider);
SwingUtilities.invokeLater(() -> provider.closeComponent());
waitForPostedSwingRunnables();
waitForSwing();
Window w = windowForComponent(table);
OptionDialog d = waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
pressButtonByText(d.getComponent(), "Yes");
waitForPostedSwingRunnables();
waitForSwing();
assertTrue(tool.isVisible(provider));
String str = findLabelStr(w, "Tool Status");
@ -349,19 +356,19 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
for (int i = 0; i < count; i++) {
SwingUtilities.invokeAndWait(() -> deleteAction.actionPerformed(new ActionContext()));
waitForPostedSwingRunnables();
runSwing(() -> deleteAction.actionPerformed(new ActionContext()));
waitForSwing();
}
final ComponentProvider provider =
waitForComponentProvider(tool.getToolFrame(), EnumEditorProvider.class, 1500);
waitForComponentProvider(EnumEditorProvider.class);
assertNotNull(provider);
SwingUtilities.invokeLater(() -> provider.closeComponent());
waitForPostedSwingRunnables();
OptionDialog d = waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
waitForSwing();
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
pressButtonByText(d.getComponent(), "No");
waitForPostedSwingRunnables();
waitForSwing();
assertTrue(!tool.isVisible(provider));
}
@ -379,19 +386,19 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
for (int i = 0; i < count; i++) {
SwingUtilities.invokeAndWait(() -> deleteAction.actionPerformed(new ActionContext()));
waitForPostedSwingRunnables();
runSwing(() -> deleteAction.actionPerformed(new ActionContext()));
waitForSwing();
}
final ComponentProvider provider =
waitForComponentProvider(tool.getToolFrame(), EnumEditorProvider.class, 1500);
waitForComponentProvider(EnumEditorProvider.class);
assertNotNull(provider);
SwingUtilities.invokeLater(() -> provider.closeComponent());
waitForPostedSwingRunnables();
OptionDialog d = waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
waitForSwing();
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
pressButtonByText(d.getComponent(), "Cancel");
waitForPostedSwingRunnables();
waitForSwing();
assertTrue(tool.isVisible(provider));
// add an entry so the tear down works properly
@ -412,17 +419,17 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final DockingActionIf deleteAction = getAction(plugin, "Delete Enum Value");
assertTrue(deleteAction.isEnabled());
SwingUtilities.invokeAndWait(() -> deleteAction.actionPerformed(new ActionContext()));
waitForPostedSwingRunnables();
runSwing(() -> deleteAction.actionPerformed(new ActionContext()));
waitForSwing();
assertTrue(table.isRowSelected(0));
final DockingActionIf applyAction = getAction(plugin, "Apply Enum Changes");
assertTrue(applyAction.isEnabled());
SwingUtilities.invokeAndWait(() -> applyAction.actionPerformed(new ActionContext()));
runSwing(() -> applyAction.actionPerformed(new ActionContext()));
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
assertEquals(5, model.getRowCount());
assertEquals(5, enummDt.getCount());
@ -434,11 +441,11 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
JTextField nameField = getTextField(panel, "Name");
nameField.setText("MyColors");
});
waitForPostedSwingRunnables();
waitForSwing();
applyChanges(true);
assertEquals("MyColors", enummDt.getName());
}
@ -446,8 +453,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testDuplicateName() throws Exception {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 0x10);
@ -467,29 +476,28 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
SwingUtilities.invokeLater(() -> plugin.edit(enummDt));
waitForPostedSwingRunnables();
runSwing(() -> plugin.edit(enummDt), false);
waitForSwing();
final EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
JTextField nameField = getTextField(panel, "Name");
nameField.setText("FavoriteColors");
});
waitForPostedSwingRunnables();
waitForSwing();
applyChanges(false);
Window window = windowForComponent(panel);
final OptionDialog d = waitForDialogComponent(window, OptionDialog.class, 2000);
assertNotNull(d);
assertEquals("Duplicate Name", d.getTitle());
DialogComponentProvider dialog = waitForErrorDialog();
assertNotNull(dialog);
assertEquals("Duplicate Name", dialog.getTitle());
assertEquals("Colors", enummDt.getName());
pressButtonByText(d, "OK");
waitForPostedSwingRunnables();
close(dialog);
waitForSwing();
assertTrue(!getAction(plugin, "Apply Enum Changes").isEnabled());
assertFalse(getAction(plugin, "Apply Enum Changes").isEnabled());
}
@ -521,7 +529,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
tf.setText("0x0");
editor.stopCellEditing();
});
waitForPostedSwingRunnables();
waitForSwing();
Window w = windowForComponent(table);
String str = findLabelStr(w, "Tool Status");
// assertEquals("Colors enum value 0 already assigned", str);
@ -538,8 +546,8 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final JTextField descField = getTextField(panel, "Description");
assertEquals("This is a set of Colors", descField.getText());
SwingUtilities.invokeAndWait(() -> descField.setText("My Favorite colors"));
waitForPostedSwingRunnables();
runSwing(() -> descField.setText("My Favorite colors"));
waitForSwing();
applyChanges(true);
assertEquals("My Favorite colors", enumDt.getDescription());
@ -553,8 +561,8 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
final JTextField descField = getTextField(panel, "Description");
SwingUtilities.invokeAndWait(() -> descField.setText(""));
waitForPostedSwingRunnables();
runSwing(() -> descField.setText(""));
waitForSwing();
applyChanges(true);
assertEquals("", enumDt.getDescription());
@ -568,19 +576,19 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
final JTable table = panel.getTable();
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
TableColumnModel colModel = table.getColumnModel();
colModel.moveColumn(1, 0);
});
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("Value", table.getColumnName(0));
assertEquals("Name", table.getColumnName(1));
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
TableColumnModel colModel = table.getColumnModel();
colModel.moveColumn(0, 1);
});
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("Name", table.getColumnName(0));
assertEquals("Value", table.getColumnName(1));
@ -597,7 +605,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
// delete a row
table.setRowSelectionInterval(0, 0);
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
DockingActionIf action = getAction(plugin, "Delete Enum Value");
action.actionPerformed(new ActionContext());
});
@ -622,28 +630,28 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
EnumTableModel model = (EnumTableModel) table.getModel();
int origRowCount = model.getRowCount();
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
DockingActionIf action = getAction(plugin, "Add Enum Value");
action.actionPerformed(new ActionContext());
action.actionPerformed(new ActionContext());
});
waitForPostedSwingRunnables();
waitForSwing();
applyChanges(true);
// make more changes
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
DockingActionIf action = getAction(plugin, "Add Enum Value");
action.actionPerformed(new ActionContext());
action.actionPerformed(new ActionContext());
});
waitForPostedSwingRunnables();
waitForSwing();
undo(false);
OptionDialog d = waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
// yes to reload the enum data type
final JButton button = findButtonByText(d.getComponent(), "Yes");
assertNotNull(button);
SwingUtilities.invokeAndWait(() -> button.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
runSwing(() -> button.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertEquals(origRowCount, model.getRowCount());
}
@ -656,7 +664,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final JTable table = panel.getTable();
final EnumTableModel model = (EnumTableModel) table.getModel();
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
int lastRow = model.getRowCount() - 1;
if (lastRow >= 0) {
table.addRowSelectionInterval(lastRow, lastRow);
@ -665,10 +673,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
action.actionPerformed(new ActionContext());
action.actionPerformed(new ActionContext());
});
waitForPostedSwingRunnables();
waitForSwing();
applyChanges(true);
// make more changes
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
int lastRow = model.getRowCount() - 1;
if (lastRow >= 0) {
table.addRowSelectionInterval(lastRow, lastRow);
@ -677,16 +685,16 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
action.actionPerformed(new ActionContext());
action.actionPerformed(new ActionContext());
});
waitForPostedSwingRunnables();
waitForSwing();
int rowCount = model.getRowCount();
undo(false);
OptionDialog d = waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
// not to not reload the enum data type
final JButton button = findButtonByText(d.getComponent(), "No");
assertNotNull(button);
SwingUtilities.invokeAndWait(() -> button.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
runSwing(() -> button.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertEquals(rowCount, model.getRowCount());
}
@ -742,7 +750,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
private void addEntry(final JTable table, final EnumTableModel model, final String name,
final long value) throws Exception {
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
int lastRow = model.getRowCount() - 1;
if (lastRow >= 0) {
table.addRowSelectionInterval(lastRow, lastRow);
@ -750,14 +758,14 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
DockingActionIf addAction = getAction(plugin, "Add Enum Value");
addAction.actionPerformed(new ActionContext());
});
waitForPostedSwingRunnables();
waitForSwing();
final int newRow = model.getRowCount() - 1;
// change entry
SwingUtilities.invokeAndWait(() -> table.addRowSelectionInterval(newRow, newRow));
runSwing(() -> table.addRowSelectionInterval(newRow, newRow));
Rectangle rect = table.getCellRect(newRow, EnumTableModel.NAME_COL, true);
clickMouse(table, 1, rect.x, rect.y, 2, 0);
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
TableCellEditor editor = table.getCellEditor(newRow, EnumTableModel.NAME_COL);
Component c = editor.getTableCellEditorComponent(table,
model.getValueAt(newRow, EnumTableModel.NAME_COL), true, newRow,
@ -766,11 +774,11 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
tf.setText(name);
editor.stopCellEditing();
});
waitForPostedSwingRunnables();
waitForSwing();
rect = table.getCellRect(newRow, EnumTableModel.VALUE_COL, true);
clickMouse(table, 1, rect.x + 1, rect.y + 1, 2, 0);
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
TableCellEditor editor = table.getCellEditor(newRow, EnumTableModel.VALUE_COL);
Component c = editor.getTableCellEditorComponent(table,
@ -780,7 +788,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
tf.setText("0x" + Long.toHexString(value));
editor.stopCellEditing();
});
waitForPostedSwingRunnables();
waitForSwing();
}
private void applyChanges(boolean doWait) throws Exception {
@ -789,13 +797,13 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
assertTrue(applyAction.isEnabled());
Runnable r = () -> applyAction.actionPerformed(new ActionContext());
if (doWait) {
SwingUtilities.invokeAndWait(r);
runSwing(r);
program.flushEvents();
}
else {
SwingUtilities.invokeLater(r);
}
waitForPostedSwingRunnables();
waitForSwing();
}
@ -818,8 +826,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
}
private Enum editSampleEnum() {
Category cat = program.getListing().getDataTypeManager().getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
Category cat = program.getListing()
.getDataTypeManager()
.getCategory(
new CategoryPath(CategoryPath.ROOT, "Category1"));
final Enum enumm = new EnumDataType("Colors", 1);
enumm.add("Red", 0);
enumm.add("Green", 0x10);
@ -833,10 +843,10 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
final Enum enumDt = (Enum) cat.addDataType(enumm, DataTypeConflictHandler.DEFAULT_HANDLER);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
SwingUtilities.invokeLater(() -> plugin.edit(enumDt));
waitForPostedSwingRunnables();
waitForSwing();
return enumDt;
}
@ -851,12 +861,12 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
}
};
if (doWait) {
SwingUtilities.invokeAndWait(r);
runSwing(r);
}
else {
SwingUtilities.invokeLater(r);
}
waitForPostedSwingRunnables();
waitForSwing();
}
}

View file

@ -17,14 +17,13 @@ package ghidra.app.plugin.core.function;
import static org.junit.Assert.*;
import javax.swing.JDialog;
import javax.swing.JTextField;
import org.junit.*;
import docking.AbstractErrDialog;
import docking.ActionContext;
import docking.action.DockingActionIf;
import docking.widgets.MultiLineLabel;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.util.viewer.field.FunctionSignatureFieldFactory;
import ghidra.framework.plugintool.PluginTool;
@ -70,30 +69,25 @@ public class ThunkReferenceAddressDialogTest extends AbstractGhidraHeadedIntegra
@Test
public void testSetThunkedFunction() throws Exception {
ThunkReferenceAddressDialog dialog = popupSetThunkDialog(addr(0x100194b));
ThunkReferenceAddressDialog dialog = showThunkDialog(addr(0x100194b));
JTextField textEntryField = findComponent(dialog, JTextField.class);
assertNotNull(textEntryField);
// Invalid Entry
setText(textEntryField, "bar");
pressButtonByText(dialog, "OK", false);
JDialog errorDialog = waitForJDialog("Invalid Entry Error");
MultiLineLabel errorLabel =
(MultiLineLabel) findComponentByName(errorDialog, "MESSAGE-COMPONENT");
assertNotNull(errorLabel);
assertEquals("Invalid thunk reference address or name specified: bar",
errorLabel.getLabel());
AbstractErrDialog errorDialog = waitForErrorDialog();
assertEquals("Invalid Entry Error", errorDialog.getTitle());
assertEquals(
"Invalid thunk reference address or name specified: bar",
errorDialog.getMessage());
pressButtonByText(errorDialog, "OK");
// Try again
setText(textEntryField, "IsTextUnicode");
pressButtonByText(dialog, "OK");
waitForBusyTool(tool);
@ -110,7 +104,7 @@ public class ThunkReferenceAddressDialogTest extends AbstractGhidraHeadedIntegra
@Test
public void testSetThunkedFunctionWithNamespace() throws Exception {
ThunkReferenceAddressDialog dialog = popupSetThunkDialog(addr(0x100194b));
ThunkReferenceAddressDialog dialog = showThunkDialog(addr(0x100194b));
JTextField textEntryField = findComponent(dialog, JTextField.class);
assertNotNull(textEntryField);
@ -130,19 +124,10 @@ public class ThunkReferenceAddressDialogTest extends AbstractGhidraHeadedIntegra
}
// @Test
// public void testClearThunkedFunction() throws Exception {
//
// testSetThunkedFunctionWithNamespace(); // sets thunk
//
// revertThunk.actionPerformed(context);
//
// }
@Test
public void testSetThunkedFunctionWithOriginalName() throws Exception {
ThunkReferenceAddressDialog dialog = popupSetThunkDialog(addr(0x100194b));
ThunkReferenceAddressDialog dialog = showThunkDialog(addr(0x100194b));
JTextField textEntryField = findComponent(dialog, JTextField.class);
assertNotNull(textEntryField);
@ -166,54 +151,38 @@ public class ThunkReferenceAddressDialogTest extends AbstractGhidraHeadedIntegra
@Test
public void testSetThunkedFunctionWithOriginalNameConflict() throws Exception {
int txId = program.startTransaction("add label");
try {
tx(program, () -> {
program.getSymbolTable().createLabel(addr(0x1001900), "_Zxyz", SourceType.USER_DEFINED);
}
finally {
program.endTransaction(txId, true);
}
ThunkReferenceAddressDialog dialog = popupSetThunkDialog(addr(0x100194b));
});
ThunkReferenceAddressDialog dialog = showThunkDialog(addr(0x100194b));
JTextField textEntryField = findComponent(dialog, JTextField.class);
assertNotNull(textEntryField);
// Multiple Symbols
setText(textEntryField, "_Zxyz");
pressButtonByText(dialog, "OK", false);
JDialog errorDialog = waitForJDialog("Ambiguous Symbol Name");
MultiLineLabel errorLabel =
(MultiLineLabel) findComponentByName(errorDialog, "MESSAGE-COMPONENT");
assertNotNull(errorLabel);
AbstractErrDialog errorDialog = waitForErrorDialog();
assertEquals("Ambiguous Symbol Name", errorDialog.getTitle());
assertEquals(
"Specified symbol is ambiguous. Try full namespace name, mangled name or address.",
errorLabel.getLabel());
errorDialog.getMessage());
pressButtonByText(errorDialog, "OK");
waitForBusyTool(tool);
Function f = program.getFunctionManager().getFunctionAt(addr(0x100194b));
assertFalse(f.isThunk());
setText(textEntryField, "LibFoo::xyz");
pressButtonByText(dialog, "OK", false);
waitForBusyTool(tool);
Function thunkedFunction = f.getThunkedFunction(false);
assertNotNull(thunkedFunction);
assertTrue(thunkedFunction.isExternal());
assertEquals("LibFoo::xyz", thunkedFunction.getName(true));
}
private ThunkReferenceAddressDialog popupSetThunkDialog(Address address) {
private ThunkReferenceAddressDialog showThunkDialog(Address address) {
codeBrowserPlugin.goToField(address, FunctionSignatureFieldFactory.FIELD_NAME, 0, 0);
waitForBusyTool(tool);

View file

@ -39,7 +39,7 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.TestEnv;
import ghidra.util.task.TaskMonitorAdapter;
import ghidra.util.task.TaskMonitor;
public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest {
@ -52,10 +52,6 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
private JTable table;
private TableModel model;
public MemoryMapProvider3Test() {
super();
}
private Program buildProgram(String programName) throws Exception {
ProgramBuilder builder = new ProgramBuilder(programName, ProgramBuilder._TOY);
builder.createMemory(".text", Long.toHexString(0x1001000), 0x6600);
@ -102,7 +98,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
waitForDialogComponent(SplitBlockDialog.class);
assertNotNull(d);
JTextField blockOneName =
(JTextField) findComponentByName(d.getComponent(), "BlockOneName");
@ -142,21 +138,21 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
assertEquals("010075ff", blockTwoEnd.getText());
assertEquals("-- No Value --", blockTwoLength.getText());
assertTrue(!blockOneName.isEnabled());
assertTrue(!blockOneStart.isEnabled());
assertFalse(blockOneName.isEnabled());
assertFalse(blockOneStart.isEnabled());
assertTrue(blockOneEnd.isEnabled());
assertTrue(blockOneLength.isEnabled());
assertTrue(blockTwoName.isEnabled());
assertTrue(blockTwoStart.isEnabled());
assertTrue(!blockTwoEnd.isEnabled());
assertFalse(blockTwoEnd.isEnabled());
assertTrue(blockTwoLength.isEnabled());
assertTrue(!okButton.isEnabled());
assertFalse(okButton.isEnabled());
final JButton cancelButton = findButton(d.getComponent(), "Cancel");
JButton cancelButton = findButton(d.getComponent(), "Cancel");
SwingUtilities.invokeAndWait(
runSwing(
() -> cancelButton.getActionListeners()[0].actionPerformed(null));
}
@ -170,40 +166,40 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
waitForDialogComponent(SplitBlockDialog.class);
JTextField blockOneName =
(JTextField) findComponentByName(d.getComponent(), "BlockOneName");
assertNotNull(blockOneName);
JTextField blockOneStart =
(JTextField) findComponentByName(d.getComponent(), "BlockOneStart");
assertNotNull(blockOneStart);
final AddressInput blockOneEnd =
AddressInput blockOneEnd =
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
final RegisterField blockOneLength =
RegisterField blockOneLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockOneLength");
JTextField blockTwoName =
(JTextField) findComponentByName(d.getComponent(), "BlockTwoName");
assertNotNull(blockTwoName);
final AddressInput blockTwoStart =
AddressInput blockTwoStart =
(AddressInput) findComponentByName(d.getComponent(), "BlockTwoStart");
final JTextField blockTwoEnd =
JTextField blockTwoEnd =
(JTextField) findComponentByName(d.getComponent(), "BlockTwoEnd");
final RegisterField blockTwoLength =
RegisterField blockTwoLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> blockOneLength.setText("0x1000"));
runSwing(() -> blockOneLength.setText("0x1000"));
assertEquals(getAddr(0x01001fff), blockOneEnd.getAddress());
assertEquals(getAddr(0x01002000), blockTwoStart.getAddress());
assertEquals("010075ff", blockTwoEnd.getText());
assertEquals(0x5600, blockTwoLength.getValue().longValue());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("01001000", model.getValueAt(0, MemoryMapModel.START));
assertEquals("01001fff", model.getValueAt(0, MemoryMapModel.END));
@ -225,31 +221,31 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
final AddressInput blockOneEnd =
waitForDialogComponent(SplitBlockDialog.class);
AddressInput blockOneEnd =
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
final RegisterField blockOneLength =
RegisterField blockOneLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockOneLength");
final AddressInput blockTwoStart =
AddressInput blockTwoStart =
(AddressInput) findComponentByName(d.getComponent(), "BlockTwoStart");
final JTextField blockTwoEnd =
JTextField blockTwoEnd =
(JTextField) findComponentByName(d.getComponent(), "BlockTwoEnd");
final RegisterField blockTwoLength =
RegisterField blockTwoLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> blockOneEnd.setValue("01003000"));
runSwing(() -> blockOneEnd.setValue("01003000"));
assertEquals(0x2001, blockOneLength.getValue().longValue());
assertEquals(getAddr(0x01003001), blockTwoStart.getAddress());
assertEquals("010075ff", blockTwoEnd.getText());
assertEquals(0x45ff, blockTwoLength.getValue().longValue());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("01001000", model.getValueAt(0, MemoryMapModel.START));
assertEquals("01003000", model.getValueAt(0, MemoryMapModel.END));
@ -272,32 +268,32 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
waitForDialogComponent(SplitBlockDialog.class);
final AddressInput blockOneEnd =
AddressInput blockOneEnd =
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
final RegisterField blockOneLength =
RegisterField blockOneLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockOneLength");
final AddressInput blockTwoStart =
AddressInput blockTwoStart =
(AddressInput) findComponentByName(d.getComponent(), "BlockTwoStart");
final JTextField blockTwoEnd =
JTextField blockTwoEnd =
(JTextField) findComponentByName(d.getComponent(), "BlockTwoEnd");
final RegisterField blockTwoLength =
RegisterField blockTwoLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> blockTwoStart.setValue("01003000"));
runSwing(() -> blockTwoStart.setValue("01003000"));
assertEquals(0x2000, blockOneLength.getValue().longValue());
assertEquals(getAddr(0x01002fff), blockOneEnd.getAddress());
assertEquals("010075ff", blockTwoEnd.getText());
assertEquals(0x4600, blockTwoLength.getValue().longValue());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("01001000", model.getValueAt(0, MemoryMapModel.START));
assertEquals("01002fff", model.getValueAt(0, MemoryMapModel.END));
@ -319,29 +315,29 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
final AddressInput blockOneEnd =
waitForDialogComponent(SplitBlockDialog.class);
AddressInput blockOneEnd =
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
final RegisterField blockOneLength =
RegisterField blockOneLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockOneLength");
final JTextField blockTwoEnd =
JTextField blockTwoEnd =
(JTextField) findComponentByName(d.getComponent(), "BlockTwoEnd");
final RegisterField blockTwoLength =
RegisterField blockTwoLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> blockTwoLength.setText("0x2000"));
runSwing(() -> blockTwoLength.setText("0x2000"));
assertEquals(0x4600, blockOneLength.getValue().longValue());
assertEquals(getAddr(0x010055ff), blockOneEnd.getAddress());
assertEquals("010075ff", blockTwoEnd.getText());
assertEquals(0x2000, blockTwoLength.getValue().longValue());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("01001000", model.getValueAt(0, MemoryMapModel.START));
assertEquals("010055ff", model.getValueAt(0, MemoryMapModel.END));
@ -364,17 +360,17 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
performAction(action, false);
// find the dialog for the add
final SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
final AddressInput blockOneEnd =
SplitBlockDialog d =
waitForDialogComponent(SplitBlockDialog.class);
AddressInput blockOneEnd =
(AddressInput) findComponentByName(d.getComponent(), "BlockOneEnd");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> blockOneEnd.setValue("01000"));
assertTrue(!okButton.isEnabled());
runSwing(() -> blockOneEnd.setValue("01000"));
assertFalse(okButton.isEnabled());
assertEquals("End address must be greater than start",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -386,17 +382,17 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
performAction(action, false);
// find the dialog for the add
final SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
final AddressInput blockTwoStart =
SplitBlockDialog d =
waitForDialogComponent(SplitBlockDialog.class);
AddressInput blockTwoStart =
(AddressInput) findComponentByName(d.getComponent(), "BlockTwoStart");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> blockTwoStart.setValue("01000"));
assertTrue(!okButton.isEnabled());
runSwing(() -> blockTwoStart.setValue("01000"));
assertFalse(okButton.isEnabled());
assertEquals("Start address must be greater than original block start (01001000)",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -408,15 +404,15 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
performAction(action, false);
// find the dialog for the add
final SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
final RegisterField blockOneLength =
SplitBlockDialog d =
waitForDialogComponent(SplitBlockDialog.class);
RegisterField blockOneLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockOneLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> blockOneLength.setText(""));
assertTrue(!okButton.isEnabled());
runSwing(() -> d.close());
runSwing(() -> blockOneLength.setText(""));
assertFalse(okButton.isEnabled());
close(d);
}
@ -430,24 +426,24 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
performAction(action, false);
// find the dialog for the add
final SplitBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), SplitBlockDialog.class, 2000);
SplitBlockDialog d =
waitForDialogComponent(SplitBlockDialog.class);
final JTextField blockTwoName =
JTextField blockTwoName =
(JTextField) findComponentByName(d.getComponent(), "BlockTwoName");
final RegisterField blockTwoLength =
RegisterField blockTwoLength =
(RegisterField) findComponentByName(d.getComponent(), "BlockTwoLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
blockTwoLength.setText("0x2000");
blockTwoName.setText("split &%");
});
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
assertTrue(findLabelStr(d.getComponent(), "statusLabel").startsWith("Invalid Block Name"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -455,19 +451,19 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// create an overlay block
int transactionID = program.startTransaction("test");
memory.createInitializedBlock(".overlay", getAddr(0), 0x100, (byte) 0xa,
TaskMonitorAdapter.DUMMY_MONITOR, true);
TaskMonitor.DUMMY, true);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
int row = table.getModel().getRowCount() - 1;
table.setRowSelectionInterval(row, row);
DockingActionIf action = getAction(plugin, "Split Block");
performAction(action, false);
final OptionDialog d =
waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
OptionDialog d =
waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
assertEquals("Split Overlay Block Not Allowed", d.getTitle());
runSwing(() -> d.close());
close(d);
}
@Test
@ -475,29 +471,28 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// create an overlay block
int transactionID = program.startTransaction("test");
memory.createInitializedBlock(".overlay", getAddr(0), 0x100, (byte) 0xa,
TaskMonitorAdapter.DUMMY_MONITOR, true);
TaskMonitor.DUMMY, true);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
int row = table.getModel().getRowCount() - 1;
table.setRowSelectionInterval(row, row);
DockingActionIf action = getAction(plugin, "Expand Block Up");
performAction(action, false);
final OptionDialog d =
waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
OptionDialog d =
waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
assertEquals("Expand Overlay Block Not Allowed", d.getTitle());
runSwing(() -> d.close());
close(d);
action = getAction(plugin, "Expand Block Down");
performAction(action, false);
final OptionDialog d2 =
waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
OptionDialog d2 =
waitForDialogComponent(OptionDialog.class);
assertNotNull(d2);
assertEquals("Expand Overlay Block Not Allowed", d2.getTitle());
runSwing(() -> d2.close());
}
@Test
@ -510,29 +505,29 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
assertTrue(action.isEnabled());
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
assertNotNull(d);
assertEquals("Expand Block Up", d.getTitle());
final AddressInput start =
AddressInput start =
(AddressInput) findComponentByName(d.getComponent(), "NewStartAddress");
final JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
final RegisterField length =
JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
assertNotNull(start);
assertNotNull(end);
assertNotNull(length);
assertNotNull(okButton);
assertTrue(!okButton.isEnabled());
assertTrue(!end.isEnabled());
assertFalse(okButton.isEnabled());
assertFalse(end.isEnabled());
assertEquals(getAddr(0x01001000), start.getAddress());
assertEquals("010075ff", end.getText());
assertEquals("0x6600", length.getText());
runSwing(() -> d.close());
close(d);
}
@Test
@ -547,22 +542,22 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
waitForDialogComponent(ExpandBlockDialog.class);
final AddressInput start =
AddressInput start =
(AddressInput) findComponentByName(d.getComponent(), "NewStartAddress");
final JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
assertNotNull(end);
final RegisterField length =
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> start.setValue("00002000"));
runSwing(() -> start.setValue("00002000"));
assertEquals("0x1005600", length.getText());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertEquals(".text.exp", model.getValueAt(0, MemoryMapModel.NAME));
assertEquals("00002000", model.getValueAt(0, MemoryMapModel.START));
@ -593,21 +588,21 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
assertTrue(action.isEnabled());
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
final AddressInput start =
AddressInput start =
(AddressInput) findComponentByName(d.getComponent(), "NewStartAddress");
final RegisterField length =
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
assertNotNull(length);
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> start.setValue("01201000"));
assertTrue(!okButton.isEnabled());
runSwing(() -> start.setValue("01201000"));
assertFalse(okButton.isEnabled());
assertEquals("Start must be less than 01001000",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -622,21 +617,21 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
final AddressInput start =
waitForDialogComponent(ExpandBlockDialog.class);
AddressInput start =
(AddressInput) findComponentByName(d.getComponent(), "NewStartAddress");
final JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
final RegisterField length =
JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> length.setText("0x7600"));
runSwing(() -> length.setText("0x7600"));
assertEquals(getAddr(0x01000000), start.getAddress());
assertEquals("010075ff", end.getText());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertEquals(".text.exp", model.getValueAt(0, MemoryMapModel.NAME));
assertEquals("01000000", model.getValueAt(0, MemoryMapModel.START));
@ -667,22 +662,22 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
assertTrue(action.isEnabled());
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
final AddressInput start =
AddressInput start =
(AddressInput) findComponentByName(d.getComponent(), "NewStartAddress");
assertNotNull(start);
final RegisterField length =
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> length.setText("0x1000"));
runSwing(() -> length.setText("0x1000"));
assertTrue(!okButton.isEnabled());
assertFalse(okButton.isEnabled());
assertEquals("Block size must be greater than 6600",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -697,24 +692,24 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
assertTrue(action.isEnabled());
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
final AddressInput start =
AddressInput start =
(AddressInput) findComponentByName(d.getComponent(), "NewStartAddress");
final JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
final JButton okButton = findButton(d.getComponent(), "OK");
JTextField end = (JTextField) findComponentByName(d.getComponent(), "EndAddress");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> start.setValue("01008000"));
runSwing(() -> start.setValue("01008000"));
assertEquals("0100f3ff", end.getText());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
assertTrue(!okButton.isEnabled());
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertFalse(okButton.isEnabled());
assertEquals("Part of range (01008000, 01009fff) already exists in memory.",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -726,30 +721,30 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
assertTrue(action.isEnabled());
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
assertNotNull(d);
assertEquals("Expand Block Down", d.getTitle());
final JTextField start = (JTextField) findComponentByName(d.getComponent(), "StartAddress");
final AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
final RegisterField length =
JTextField start = (JTextField) findComponentByName(d.getComponent(), "StartAddress");
AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
assertNotNull(start);
assertNotNull(end);
assertNotNull(length);
assertNotNull(okButton);
assertTrue(!okButton.isEnabled());
assertTrue(!start.isEnabled());
assertFalse(okButton.isEnabled());
assertFalse(start.isEnabled());
assertTrue(end.isEnabled());
assertEquals("01001000", start.getText());
assertEquals(getAddr(0x010075ff), end.getAddress());
assertEquals("0x6600", length.getText());
runSwing(() -> d.close());
close(d);
}
@Test
@ -761,19 +756,19 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
waitForDialogComponent(ExpandBlockDialog.class);
final AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
final RegisterField length =
AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> end.setValue("01007700"));
runSwing(() -> end.setValue("01007700"));
assertEquals("0x6701", length.getText());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertEquals(".text.exp", model.getValueAt(0, MemoryMapModel.NAME));
assertEquals("01001000", model.getValueAt(0, MemoryMapModel.START));
@ -790,19 +785,19 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
// find the dialog for the add
ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
waitForDialogComponent(ExpandBlockDialog.class);
final AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
final RegisterField length =
AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> length.setText("0x6700"));
runSwing(() -> length.setText("0x6700"));
assertEquals(getAddr(0x10076ff), end.getAddress());
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertEquals(".text.exp", model.getValueAt(0, MemoryMapModel.NAME));
assertEquals("01001000", model.getValueAt(0, MemoryMapModel.START));
@ -820,17 +815,17 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
performAction(action, false);
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
final AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
final JButton okButton = findButton(d.getComponent(), "OK");
AddressInput end = (AddressInput) findComponentByName(d.getComponent(), "EndAddress");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> end.setValue("01007000"));
assertTrue(!okButton.isEnabled());
runSwing(() -> end.setValue("01007000"));
assertFalse(okButton.isEnabled());
assertEquals("End must be greater than 010075ff",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -842,18 +837,18 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
performAction(action, false);
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
final RegisterField length =
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> length.setText("0x670"));
assertTrue(!okButton.isEnabled());
runSwing(() -> length.setText("0x670"));
assertFalse(okButton.isEnabled());
assertEquals("Block size must be greater than 6600",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
@Test
@ -865,30 +860,28 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
performAction(action, false);
// find the dialog for the add
final ExpandBlockDialog d =
waitForDialogComponent(tool.getToolFrame(), ExpandBlockDialog.class, 2000);
ExpandBlockDialog d =
waitForDialogComponent(ExpandBlockDialog.class);
final RegisterField length =
RegisterField length =
(RegisterField) findComponentByName(d.getComponent(), "BlockLength");
final JButton okButton = findButton(d.getComponent(), "OK");
JButton okButton = findButton(d.getComponent(), "OK");
SwingUtilities.invokeAndWait(() -> length.setText("0x7600"));
runSwing(() -> length.setText("0x7600"));
assertTrue(okButton.isEnabled());
SwingUtilities.invokeAndWait(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
runSwing(() -> okButton.getActionListeners()[0].actionPerformed(null));
waitForSwing();
assertTrue(!okButton.isEnabled());
assertFalse(okButton.isEnabled());
assertEquals("Part of range (01007600, 010085ff) already exists in memory.",
findLabelStr(d.getComponent(), "statusLabel"));
runSwing(() -> d.close());
close(d);
}
///////////////////////////////////////////////////////////////////
private void showProvider() {
DockingActionIf action = getAction(plugin, "Memory Map");
performAction(action, true);
waitForPostedSwingRunnables();
waitForSwing();
provider = plugin.getMemoryMapProvider();
table = provider.getTable();
model = table.getModel();

View file

@ -20,11 +20,13 @@ import static org.junit.Assert.*;
import java.awt.Component;
import java.awt.Container;
import javax.swing.*;
import javax.swing.JButton;
import javax.swing.JTable;
import javax.swing.table.TableModel;
import org.junit.*;
import docking.AbstractErrDialog;
import docking.action.DockingActionIf;
import docking.widgets.MultiLineLabel;
import docking.widgets.OptionDialog;
@ -38,7 +40,7 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.TestEnv;
import ghidra.util.task.TaskMonitorAdapter;
import ghidra.util.task.TaskMonitor;
/**
* Tests for merging memory blocks.
@ -86,25 +88,22 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
@After
public void tearDown() throws Exception {
env.release(program);
env.dispose();
}
@Test
public void testMergeBlocks() throws Exception {
// create 4 blocks: 0-0f, 10-1f, 20-20f, 40-4f.
int transactionID = program.startTransaction("test");
memory.createInitializedBlock("block1", getAddr(0), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
memory.createInitializedBlock("block2", getAddr(0x10), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
memory.createInitializedBlock("block3", getAddr(0x20), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
memory.createInitializedBlock("block4", getAddr(0x40), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
tx(program, () -> {
memory.createInitializedBlock("block1", getAddr(0), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
memory.createInitializedBlock("block2", getAddr(0x10), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
memory.createInitializedBlock("block3", getAddr(0x20), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
memory.createInitializedBlock("block4", getAddr(0x40), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
});
assertEquals("0000004f", model.getValueAt(3, MemoryMapModel.END));
// select rows 0 through 3
@ -112,7 +111,7 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
DockingActionIf action = getAction(plugin, "Merge Blocks");
assertTrue(action.isEnabled());
performAction(action, false);
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("block1", model.getValueAt(0, MemoryMapModel.NAME));
assertEquals("00000000", model.getValueAt(0, MemoryMapModel.START));
@ -127,18 +126,17 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
@Test
public void testMergeBlocksDisjoint() throws Exception {
// create 4 blocks: 0-0f, 10-1f, 20-20f, 40-4f.
int transactionID = program.startTransaction("test");
memory.createInitializedBlock("block1", getAddr(0), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
memory.createInitializedBlock("block2", getAddr(0x10), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
memory.createInitializedBlock("block3", getAddr(0x20), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
memory.createInitializedBlock("block4", getAddr(0x40), 0x10, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
tx(program, () -> {
memory.createInitializedBlock("block1", getAddr(0), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
memory.createInitializedBlock("block2", getAddr(0x10), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
memory.createInitializedBlock("block3", getAddr(0x20), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
memory.createInitializedBlock("block4", getAddr(0x40), 0x10, (byte) 0,
TaskMonitor.DUMMY, false);
});
assertEquals("block1", model.getValueAt(0, MemoryMapModel.NAME));
assertEquals("block2", model.getValueAt(1, MemoryMapModel.NAME));
@ -153,26 +151,20 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
DockingActionIf action = getAction(plugin, "Merge Blocks");
assertTrue(action.isEnabled());
performAction(action, false);
waitForPostedSwingRunnables();
final OptionDialog d =
waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
assertNotNull(d);
assertEquals("Merge Blocks Failed", d.getTitle());
assertEquals("Can't merge blocks because they are not contiguous",
findMessage(d.getComponent()));
AbstractErrDialog d = waitForErrorDialog();
runSwing(() -> d.close());
assertEquals("Merge Blocks Failed", d.getTitle());
assertEquals("Can't merge blocks because they are not contiguous", d.getMessage());
close(d);
}
@Test
public void testMergeBlocksFarApart() throws Exception {
int transactionID = program.startTransaction("test");
memory.createInitializedBlock("block1", getAddr(0), 0x50, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
tx(program, () -> {
memory.createInitializedBlock("block1", getAddr(0), 0x50, (byte) 0,
TaskMonitor.DUMMY, false);
});
// select rows 0 and 1
table.setRowSelectionInterval(0, 1);
@ -180,20 +172,19 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
DockingActionIf action = getAction(plugin, "Merge Blocks");
assertTrue(action.isEnabled());
performAction(action, false);
waitForPostedSwingRunnables();
OptionDialog d = waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
assertNotNull(d);
waitForSwing();
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertEquals("Merge Memory Blocks", d.getTitle());
String message = findMessage(d.getComponent());
assertTrue(
message.startsWith("Merging these blocks will create 16387K extra bytes in memory"));
final JButton b = findButton(d.getComponent(), "Merge Blocks");
JButton b = findButton(d.getComponent(), "Merge Blocks");
assertNotNull(b);
SwingUtilities.invokeAndWait(() -> b.getActionListeners()[0].actionPerformed(null));
runSwing(() -> b.getActionListeners()[0].actionPerformed(null));
waitForPostedSwingRunnables();
waitForSwing();
assertEquals("block1", model.getValueAt(0, MemoryMapModel.NAME));
assertEquals("00000000", model.getValueAt(0, MemoryMapModel.START));
assertEquals("010075ff", model.getValueAt(0, MemoryMapModel.END));
@ -217,10 +208,10 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
int transactionID = program.startTransaction("test");
memory.createInitializedBlock("block1", getAddr(0), 0x50, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, false);
TaskMonitor.DUMMY, false);
program.endTransaction(transactionID, true);
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
// select rows 0 and 1
table.setRowSelectionInterval(0, 1);
@ -228,24 +219,21 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
DockingActionIf action = getAction(plugin, "Merge Blocks");
assertTrue(action.isEnabled());
performAction(action, false);
waitForPostedSwingRunnables();
OptionDialog d = waitForDialogComponent(tool.getToolFrame(), OptionDialog.class, 2000);
assertNotNull(d);
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertEquals("Merge Memory Blocks", d.getTitle());
assertTrue(findMessage(d.getComponent()).startsWith(
"Merging these blocks will create 16387K extra bytes in memory"));
final JButton b = findButton(d.getComponent(), "Cancel");
JButton b = findButton(d.getComponent(), "Cancel");
assertNotNull(b);
SwingUtilities.invokeAndWait(() -> b.getActionListeners()[0].actionPerformed(null));
runSwing(() -> b.getActionListeners()[0].actionPerformed(null));
assertEquals("0000004f", model.getValueAt(0, MemoryMapModel.END));
}
private void showProvider() {
DockingActionIf action = getAction(plugin, "Memory Map");
performAction(action, true);
waitForPostedSwingRunnables();
waitForSwing();
provider = plugin.getMemoryMapProvider();
table = provider.getTable();
model = table.getModel();

View file

@ -28,11 +28,10 @@ import javax.swing.*;
import org.junit.*;
import docking.AbstractErrDialog;
import docking.ActionContext;
import docking.action.DockingActionIf;
import docking.tool.ToolConstants;
import docking.widgets.MultiLineLabel;
import docking.widgets.OptionDialog;
import docking.widgets.table.GTable;
import docking.widgets.table.threaded.GThreadedTablePanel;
import ghidra.app.events.ProgramSelectionPluginEvent;
@ -954,12 +953,9 @@ public class SearchTextPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
}
private void closeMaxSearchResultsDialog() throws Exception {
final OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
String msg = findMessage(d.getComponent());
assertNotNull(msg);
assertTrue(msg.indexOf("Stopped search") >= 0);
runSwing(() -> d.close());
AbstractErrDialog d = waitForErrorDialog();
assertTrue(d.getMessage().contains("Stopped search"));
close(d);
waitForSwing();
}
@ -1071,22 +1067,6 @@ public class SearchTextPlugin1Test extends AbstractGhidraHeadedIntegrationTest {
return null;
}
private String findMessage(Container container) {
Component[] c = container.getComponents();
for (Component element : c) {
if (element instanceof MultiLineLabel) {
return ((MultiLineLabel) element).getLabel();
}
if (element instanceof Container) {
String str = findMessage((Container) element);
if (str != null) {
return str;
}
}
}
return null;
}
private SearchTextDialog getDialog() throws Exception {
runSwing(() -> searchAction.actionPerformed(provider.getActionContext(null)));
return plugin.getSearchDialog();

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.plugin.core.string;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.nio.charset.StandardCharsets;
@ -83,7 +83,7 @@ public class StringTableProviderTest extends AbstractGhidraHeadedIntegrationTest
CodeViewerProvider cbProvider = cb.getProvider();
SwingUtilities.invokeLater(
() -> searchAction.actionPerformed(cbProvider.getActionContext(null)));
waitForPostedSwingRunnables();
waitForSwing();
return getDialogComponent(SearchStringDialog.class);
}
@ -317,7 +317,7 @@ public class StringTableProviderTest extends AbstractGhidraHeadedIntegrationTest
selectRows(address); // string abcefg is here
performAction(makeStringAction, false);
waitForPostedSwingRunnables();
waitForSwing();
OptionDialog dialogProvider = getDialogComponent(OptionDialog.class);
assertNotNull(dialogProvider);
@ -435,13 +435,9 @@ public class StringTableProviderTest extends AbstractGhidraHeadedIntegrationTest
}
private void createDataAt(Address addr) throws Exception {
int id = program.startTransaction("test");
try {
tx(program, () -> {
program.getListing().createData(addr, new ByteDataType());
}
finally {
program.endTransaction(id, true);
}
});
}
private void setCheckbox(final JCheckBox checkbox, final boolean selected) {
@ -527,15 +523,6 @@ public class StringTableProviderTest extends AbstractGhidraHeadedIntegrationTest
}
// protected void waitForTable() throws Exception {
// int nWaits = 0;
// while (model.isBusy() && nWaits++ < 500) {
// Thread.sleep(50);
// }
//
// assertTrue("Timed-out waiting for table model to update.", nWaits < 500);
// }
private void toggleDefinedStateButtons(final boolean defined, final boolean undefined,
final boolean partial, final boolean conflicting) {
runSwing(() -> {

View file

@ -24,9 +24,9 @@ import javax.swing.*;
import org.junit.After;
import org.junit.Before;
import docking.AbstractErrDialog;
import docking.action.DockingActionIf;
import docking.test.AbstractDockingTest;
import docking.widgets.OptionDialog;
import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.tree.GTree;
import docking.widgets.tree.GTreeNode;
@ -55,16 +55,17 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.TestEnv;
import ghidra.util.SystemUtilities;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitorAdapter;
import ghidra.util.task.TaskMonitor;
/**
* Tests for the symbol tree plugin.
*/
public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhidraHeadedIntegrationTest {
public abstract class AbstractSymbolTreePluginExternalsTest
extends AbstractGhidraHeadedIntegrationTest {
protected static final String GZF_NAME = "WinHelloCPP.exe";
protected static final String PROGRAM_NAME = "WinHelloCPP";
protected static final String EXTERNAL_PROGRAM_PATHNAME = "/" + PROGRAM_NAME;
protected static String GZF_NAME = "WinHelloCPP.exe";
protected static String PROGRAM_NAME = "WinHelloCPP";
protected static String EXTERNAL_PROGRAM_PATHNAME = "/" + PROGRAM_NAME;
protected TestEnv env;
protected PluginTool tool;
@ -107,9 +108,6 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
env.showTool();
}
/*
* @see TestCase#tearDown()
*/
@After
public void tearDown() throws Exception {
closeProgram();
@ -120,10 +118,10 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
throws Exception {
selectExternalLocation(libraryName, name);
performAction(editExternalLocationAction, util.getProvider(), false);
waitForPostedSwingRunnables();
waitForSwing();
EditExternalLocationDialog createDialog = AbstractDockingTest.waitForDialogComponent(
plugin.getTool().getToolFrame(), EditExternalLocationDialog.class, 2000);
EditExternalLocationDialog.class);
waitForBusyTool(tool);
return createDialog;
}
@ -151,11 +149,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
}
}
//==================================================================================================
// Private Methods
//==================================================================================================
protected void changeToFunction(final EditExternalLocationDialog createDialog,
protected void changeToFunction(EditExternalLocationDialog createDialog,
boolean isFunction) {
EditExternalLocationPanel extLocPanel = findComponent(
createDialog.getComponent().getRootPane(), EditExternalLocationPanel.class);
@ -163,8 +157,8 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
functionCheckBox.setSelected(isFunction);
}
protected ExternalLocation setupExternalLocation(final String library, final String label,
final Address address, final SourceType sourceType, boolean isFunction)
protected ExternalLocation setupExternalLocation(String library, String label,
Address address, SourceType sourceType, boolean isFunction)
throws InvalidInputException, DuplicateNameException {
boolean success = false;
int transactionID =
@ -187,19 +181,19 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
}
}
protected ExternalLocation setupExternalLocation(final String library, final String label,
final Address address, final SourceType sourceType)
protected ExternalLocation setupExternalLocation(String library, String label,
Address address, SourceType sourceType)
throws InvalidInputException, DuplicateNameException {
return setupExternalLocation(library, label, address, sourceType, false);
}
protected ExternalLocation setupExternalFunction(final String library, final String label,
final Address address, final SourceType sourceType)
protected ExternalLocation setupExternalFunction(String library, String label,
Address address, SourceType sourceType)
throws InvalidInputException, DuplicateNameException {
return setupExternalLocation(library, label, address, sourceType, true);
}
protected Namespace addNamespace(final String libraryName, final String namespace)
protected Namespace addNamespace(String libraryName, String namespace)
throws InvalidInputException {
boolean success = false;
int transactionID = program.startTransaction(
@ -217,7 +211,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
}
}
protected Namespace getLibraryScope(final String libaryName) {
protected Namespace getLibraryScope(String libaryName) {
Symbol s = program.getSymbolTable().getLibrarySymbol(libaryName);
if (s instanceof LibrarySymbol) {
return (Namespace) s.getObject();
@ -225,27 +219,27 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
return null;
}
protected void closeExternalLocation(final EditExternalLocationDialog createDialog,
final String buttonText) {
protected void closeExternalLocation(EditExternalLocationDialog createDialog,
String buttonText) {
pressButtonByText(createDialog.getComponent(), buttonText);
assertFalse(createDialog.isShowing());
waitForPostedSwingRunnables();
waitForSwing();
}
protected GTreeNode selectLibraryNode(final String libraryName) throws Exception {
protected GTreeNode selectLibraryNode(String libraryName) throws Exception {
flushAndWaitForTree();
GTreeNode importsNode = rootNode.getChild("Imports");
assertNotNull(importsNode);
util.expandNode(importsNode);
waitForPostedSwingRunnables();
waitForSwing();
flushAndWaitForTree();
GTreeNode advapiNode = importsNode.getChild(libraryName);
assertNotNull(advapiNode);
tree.expandPath(advapiNode);
tree.setSelectedNode(advapiNode);
waitForPostedSwingRunnables();
waitForSwing();
flushAndWaitForTree();
GTreeNode selectedNode = util.getSelectedNode();
assertEquals(advapiNode, selectedNode);
@ -254,26 +248,26 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
return advapiNode;
}
protected GTreeNode selectExternalLocation(final String libraryName,
final String externalLocation) throws Exception {
protected GTreeNode selectExternalLocation(String libraryName,
String externalLocation) throws Exception {
flushAndWaitForTree();
GTreeNode importsNode = rootNode.getChild("Imports");
assertNotNull(importsNode);
util.expandNode(importsNode);
waitForPostedSwingRunnables();
waitForSwing();
flushAndWaitForTree();
GTreeNode advapiNode = importsNode.getChild(libraryName);
assertNotNull(advapiNode);
util.expandNode(advapiNode);
waitForPostedSwingRunnables();
waitForSwing();
flushAndWaitForTree();
GTreeNode locationNode = advapiNode.getChild(externalLocation);
assertNotNull(locationNode);
tree.setSelectedNode(locationNode);
waitForPostedSwingRunnables();
waitForSwing();
flushAndWaitForTree();
GTreeNode selectedNode = util.getSelectedNode();
assertEquals(locationNode, selectedNode);
@ -282,8 +276,8 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
return locationNode;
}
protected void checkExternalLocationPath(final EditExternalLocationDialog createDialog,
final String externalProgramPath) {
protected void checkExternalLocationPath(EditExternalLocationDialog createDialog,
String externalProgramPath) {
SystemUtilities.runSwingNow(() -> {
EditExternalLocationPanel panel = findComponent(
createDialog.getComponent().getRootPane(), EditExternalLocationPanel.class);
@ -294,8 +288,8 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
});
}
protected void checkExternalLibraryName(final EditExternalLocationDialog createDialog,
final String expectedName) {
protected void checkExternalLibraryName(EditExternalLocationDialog createDialog,
String expectedName) {
SystemUtilities.runSwingNow(() -> {
EditExternalLocationPanel panel = findComponent(
createDialog.getComponent().getRootPane(), EditExternalLocationPanel.class);
@ -306,8 +300,8 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
});
}
protected void chooseExternalLibraryName(final EditExternalLocationDialog createDialog,
final String libraryName) {
protected void chooseExternalLibraryName(EditExternalLocationDialog createDialog,
String libraryName) {
SystemUtilities.runSwingNow(() -> {
EditExternalLocationPanel panel = findComponent(
createDialog.getComponent().getRootPane(), EditExternalLocationPanel.class);
@ -317,8 +311,8 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
});
}
protected void typeExternalLibraryName(final EditExternalLocationDialog createDialog,
final String libraryName) {
protected void typeExternalLibraryName(EditExternalLocationDialog createDialog,
String libraryName) {
runSwing(() -> {
EditExternalLocationPanel panel = findComponent(
@ -335,8 +329,8 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
});
}
protected void checkExternalLocationPathEndsWith(final EditExternalLocationDialog createDialog,
final String externalProgramPathEndsWith) {
protected void checkExternalLocationPathEndsWith(EditExternalLocationDialog createDialog,
String externalProgramPathEndsWith) {
EditExternalLocationPanel panel = findComponent(createDialog.getComponent().getRootPane(),
EditExternalLocationPanel.class);
Object pathTextObj = getInstanceField("extLibPathTextField", panel);
@ -347,16 +341,16 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
text.endsWith(externalProgramPathEndsWith));
}
protected void chooseProgram(final Project project, final String programName) {
protected void chooseProgram(Project project, String programName) {
final DataTreeDialog chooseDialog = AbstractDockingTest.waitForDialogComponent(
plugin.getTool().getToolFrame(), DataTreeDialog.class, 2000);
DataTreeDialog chooseDialog = AbstractDockingTest.waitForDialogComponent(
DataTreeDialog.class);
ProjectData projectData = project.getProjectData();
DomainFolder folder = projectData.getFolder("/");
assertNotNull(folder);
final DomainFile file = folder.getFile(programName);
DomainFile file = folder.getFile(programName);
assertNotNull(file);
setFileInDataTreeDialog(chooseDialog, file);
@ -368,15 +362,15 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
flushAndWaitForTree();
}
protected void chooseProgramButCancel(final Project project, final String programName) {
protected void chooseProgramButCancel(Project project, String programName) {
final DataTreeDialog chooseDialog = AbstractDockingTest.waitForDialogComponent(
plugin.getTool().getToolFrame(), DataTreeDialog.class, 2000);
DataTreeDialog chooseDialog = AbstractDockingTest.waitForDialogComponent(
DataTreeDialog.class);
ProjectData projectData = project.getProjectData();
DomainFolder folder = projectData.getFolder("/");
assertNotNull(folder);
final DomainFile file = folder.getFile(programName);
DomainFile file = folder.getFile(programName);
assertNotNull(file);
setFileInDataTreeDialog(chooseDialog, file);
@ -390,13 +384,9 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
protected void closeErrorDialog(String expectedTitle) {
final OptionDialog errorDialog = AbstractDockingTest.waitForDialogComponent(
plugin.getTool().getToolFrame(), OptionDialog.class, 2000);
String actualTitle = errorDialog.getTitle();
pressButtonByText(errorDialog.getComponent().getRootPane(), "OK", false);
AbstractErrDialog d = waitForErrorDialog();
String actualTitle = d.getTitle();
close(d);
assertEquals(expectedTitle, actualTitle);
waitForBusyTool(tool);
@ -404,7 +394,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
flushAndWaitForTree();
}
protected void checkExternalLocationLabel(final EditExternalLocationDialog createDialog,
protected void checkExternalLocationLabel(EditExternalLocationDialog createDialog,
String label) {
EditExternalLocationPanel extLocPanel = findComponent(
createDialog.getComponent().getRootPane(), EditExternalLocationPanel.class);
@ -414,7 +404,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
assertEquals(label, text);
}
protected void setExternalLocationLabel(final EditExternalLocationDialog createDialog,
protected void setExternalLocationLabel(EditExternalLocationDialog createDialog,
String label) {
runSwing(() -> {
EditExternalLocationPanel extLocPanel = findComponent(
@ -425,7 +415,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
});
}
protected void checkExternalLocationAddressInput(final EditExternalLocationDialog createDialog,
protected void checkExternalLocationAddressInput(EditExternalLocationDialog createDialog,
String space, String address) {
EditExternalLocationPanel extLocPanel = findComponent(
createDialog.getComponent().getRootPane(), EditExternalLocationPanel.class);
@ -443,7 +433,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
assertEquals(address, currentAddress);
}
protected void setExternalLocationAddressInput(final EditExternalLocationDialog createDialog,
protected void setExternalLocationAddressInput(EditExternalLocationDialog createDialog,
AddressSpace addressSpace, String address) {
runSwing(() -> {
EditExternalLocationPanel extLocPanel = findComponent(
@ -468,13 +458,13 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
Address address = program.getAddressFactory().getAddress(startAddress);
Memory memory = program.getMemory();
memory.createInitializedBlock(name, address, length, (byte) 0,
TaskMonitorAdapter.DUMMY_MONITOR, true);
TaskMonitor.DUMMY, true);
program.endTransaction(transactionID, true);
}
protected void closeProgram() throws Exception {
final ProgramManager pm = tool.getService(ProgramManager.class);
SwingUtilities.invokeAndWait(() -> pm.closeProgram());
ProgramManager pm = tool.getService(ProgramManager.class);
runSwing(() -> pm.closeProgram());
}
protected void showSymbolTree() throws Exception {
@ -514,26 +504,26 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
assertNotNull(goToExtLocAction);
}
protected void pressDataTreeDialogOK(final DataTreeDialog dialog) {
protected void pressDataTreeDialogOK(DataTreeDialog dialog) {
pressButtonByText(dialog.getComponent(), "OK");
assertFalse(dialog.isShowing());
waitForPostedSwingRunnables();
waitForSwing();
}
protected void pressDataTreeDialogCancel(final DataTreeDialog dialog) {
protected void pressDataTreeDialogCancel(DataTreeDialog dialog) {
pressButtonByText(dialog.getComponent(), "Cancel");
assertFalse(dialog.isShowing());
waitForPostedSwingRunnables();
waitForSwing();
}
protected void setFileInDataTreeDialog(final DataTreeDialog dialog, final DomainFile file) {
protected void setFileInDataTreeDialog(DataTreeDialog dialog, DomainFile file) {
runSwing(() -> dialog.selectDomainFile(file), true);
waitForDialogTree(dialog);
}
protected void waitForDialogTree(DataTreeDialog dialog) {
waitForPostedSwingRunnables();
waitForSwing();
ProjectDataTreePanel treePanel =
(ProjectDataTreePanel) getInstanceField("treePanel", dialog);
DataTree dataTree = treePanel.getDataTree();
@ -542,7 +532,7 @@ public abstract class AbstractSymbolTreePluginExternalsTest extends AbstractGhid
protected void flushAndWaitForTree() {
program.flushEvents();
waitForPostedSwingRunnables();
waitForSwing();
util.waitForTree();
}
}

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.util.viewer.field;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.awt.*;
@ -32,6 +32,7 @@ import ghidra.app.nav.Navigatable;
import ghidra.app.nav.TestDummyNavigatable;
import ghidra.app.services.*;
import ghidra.framework.model.*;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.framework.plugintool.TestDummyServiceProvider;
import ghidra.framework.project.ProjectDataService;
import ghidra.program.database.ProgramBuilder;
@ -247,7 +248,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(programName));
assertTrue(spyNavigatable.navigatedTo(programName));
@ -257,7 +258,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
public void testProgramAnnotation_ProgramNameAndAddress() {
String programName = OTHER_PROGRAM_NAME;
String address = "01001014"; // some non-start addresss
String address = "01001014"; // some non-start address
String annotationText = "{@program " + programName + "@" + address + "}";
String rawComment = "My comment - " + annotationText;
AttributedString prototype = prototype();
@ -274,7 +275,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(programName));
assertTrue(spyNavigatable.navigatedTo(programName, address));
@ -284,7 +285,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
public void testProgramAnnotation_ProgramNameAndAddress_InvalidAddress() {
String programName = OTHER_PROGRAM_NAME;
String address = "01FFFFFF"; // some non-start addresss
String address = "01FFFFFF"; // some non-start address
String annotationText = "{@program " + programName + "@" + address + "}";
String rawComment = "My comment - " + annotationText;
AttributedString prototype = prototype();
@ -301,14 +302,13 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertErrorDialog("No Symbol");
assertTrue(spyServiceProvider.programOpened(programName));
assertTrue(spyServiceProvider.programClosed(programName));
assertFalse(spyNavigatable.navigatedTo(programName, address));
Window window = waitForWindowByTitleContaining("No Symbol");
window.setVisible(false);
}
@Test
@ -332,7 +332,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(programName));
assertTrue(spyNavigatable.navigatedTo(programName, symbol));
@ -359,14 +359,13 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertErrorDialog("No Symbol");
assertTrue(spyServiceProvider.programOpened(programName));
assertTrue(spyServiceProvider.programClosed(programName));
assertFalse(spyNavigatable.navigatedTo(programName, symbol));
Window window = waitForWindowByTitleContaining("No Symbol");
window.setVisible(false);
}
@Test
@ -390,7 +389,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(programName));
assertTrue(spyNavigatable.navigatedTo(programName, symbol));
@ -416,12 +415,11 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertErrorDialog("No Program");
assertFalse(spyServiceProvider.programOpened(programName));
Window window = waitForWindowByTitleContaining("No Program");
window.setVisible(false);
}
@Test
@ -430,8 +428,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
String addressString = "1001000";
Address address = program.getAddressFactory().getAddress(addressString);
String addresstring = "1001000";
// path in comment
String otherProgramPath = "folder1/folder2/program_f1_f2.exe";
@ -440,25 +437,24 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
String realPath = "folder1/program_f1_f2.exe";
addFakeProgramByPath(spyServiceProvider, realPath);
String annotationText = "{@program " + otherProgramPath + "@" + addressString + "}";
String annotationText = "{@program " + otherProgramPath + "@" + addresstring + "}";
String rawComment = "My comment - " + annotationText;
AttributedString prototype = prototype();
FieldElement element =
CommentUtils.parseTextForAnnotations(rawComment, program, prototype, 0);
String displayString = element.getText();
assertEquals("My comment - " + otherProgramPath + "@" + addressString, displayString);
assertEquals("My comment - " + otherProgramPath + "@" + addresstring, displayString);
//
// When clicking an element with bad path program should not open
//
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertErrorDialog("No Folder");
assertFalse(spyServiceProvider.programOpened(otherProgramPath));
Window window = waitForWindowByTitleContaining("No Folder");
window.setVisible(false);
}
@Test
@ -484,7 +480,7 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
// should be opened
//
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(otherProgramPath));
assertTrue(spyNavigatable.navigatedTo(otherProgramPath));
@ -496,27 +492,27 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
String addressString = "1001000";
Address address = program.getAddressFactory().getAddress(addressString);
String addresstring = "1001000";
Address address = program.getAddressFactory().getAddress(addresstring);
String otherProgramPath = "/folder1/folder2/program_f1_f2.exe";
addFakeProgramByPath(spyServiceProvider, otherProgramPath);
String annotationText = "{@program " + otherProgramPath + "@" + addressString + "}";
String annotationText = "{@program " + otherProgramPath + "@" + addresstring + "}";
String rawComment = "My comment - " + annotationText;
AttributedString prototype = prototype();
FieldElement element =
CommentUtils.parseTextForAnnotations(rawComment, program, prototype, 0);
String displayString = element.getText();
assertEquals("My comment - " + otherProgramPath + "@" + addressString, displayString);
assertEquals("My comment - " + otherProgramPath + "@" + addresstring, displayString);
//
// When clicking an element with only a program name, the result is that the program
// should be opened
//
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(otherProgramPath));
assertTrue(spyNavigatable.navigatedTo(otherProgramPath, address));
@ -529,28 +525,28 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
String addressString = "1001000";
Address address = program.getAddressFactory().getAddress(addressString);
String addresstring = "1001000";
Address address = program.getAddressFactory().getAddress(addresstring);
String otherProgramPath = "/folder1/folder2/program_f1_f2.exe";
String annotationPath = "\\folder1\\folder2\\program_f1_f2.exe";
addFakeProgramByPath(spyServiceProvider, otherProgramPath);
String annotationText = "{@program " + annotationPath + "@" + addressString + "}";
String annotationText = "{@program " + annotationPath + "@" + addresstring + "}";
String rawComment = "My comment - " + annotationText;
AttributedString prototype = prototype();
FieldElement element =
CommentUtils.parseTextForAnnotations(rawComment, program, prototype, 0);
String displayString = element.getText();
assertEquals("My comment - " + annotationPath + "@" + addressString, displayString);
assertEquals("My comment - " + annotationPath + "@" + addresstring, displayString);
//
// When clicking an element with only a program name, the result is that the program
// should be opened
//
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(otherProgramPath));
assertTrue(spyNavigatable.navigatedTo(otherProgramPath, address));
@ -562,28 +558,28 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
String addressString = "1001000";
Address address = program.getAddressFactory().getAddress(addressString);
String addresstring = "1001000";
Address address = program.getAddressFactory().getAddress(addresstring);
String otherProgramPath = "folder1/folder2/program_f1_f2.exe";
String annotationPath = "folder1\\folder2\\program_f1_f2.exe";
addFakeProgramByPath(spyServiceProvider, otherProgramPath);
String annotationText = "{@program " + annotationPath + "@" + addressString + "}";
String annotationText = "{@program " + annotationPath + "@" + addresstring + "}";
String rawComment = "My comment - " + annotationText;
AttributedString prototype = prototype();
FieldElement element =
CommentUtils.parseTextForAnnotations(rawComment, program, prototype, 0);
String displayString = element.getText();
assertEquals("My comment - " + annotationPath + "@" + addressString, displayString);
assertEquals("My comment - " + annotationPath + "@" + addresstring, displayString);
//
// When clicking an element with only a program name, the result is that the program
// should be opened
//
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(otherProgramPath));
assertTrue(spyNavigatable.navigatedTo(otherProgramPath, address));
@ -596,31 +592,30 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
SpyNavigatable spyNavigatable = new SpyNavigatable();
SpyServiceProvider spyServiceProvider = new SpyServiceProvider();
String addressString = "1001000";
Address address = program.getAddressFactory().getAddress(addressString);
String addresstring = "1001000";
Address address = program.getAddressFactory().getAddress(addresstring);
String otherProgramPath = "folder1/folder2/program_f1_f2.exe";
addFakeProgramByPath(spyServiceProvider, otherProgramPath);
String annotationText = "{@program " + otherProgramPath + "@" + addressString + "}";
String annotationText = "{@program " + otherProgramPath + "@" + addresstring + "}";
String rawComment = "My comment - " + annotationText;
AttributedString prototype = prototype();
FieldElement element =
CommentUtils.parseTextForAnnotations(rawComment, program, prototype, 0);
String displayString = element.getText();
assertEquals("My comment - " + otherProgramPath + "@" + addressString, displayString);
assertEquals("My comment - " + otherProgramPath + "@" + addresstring, displayString);
//
// When clicking an element with only a program name, the result is that the program
// should be opened
//
AnnotatedTextFieldElement annotatedElement = getAnnotatedTextFieldElement(element);
annotatedElement.handleMouseClicked(spyNavigatable, spyServiceProvider);
click(spyNavigatable, spyServiceProvider, annotatedElement);
assertTrue(spyServiceProvider.programOpened(otherProgramPath));
assertTrue(spyNavigatable.navigatedTo(otherProgramPath, address));
}
@Test
@ -728,6 +723,14 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
// Private Methods
//==================================================================================================
private void click(Navigatable navigatable, ServiceProvider sp,
AnnotatedTextFieldElement annotatedElement) {
// this may show an error dialog; invoke later
runSwingLater(() -> annotatedElement.handleMouseClicked(navigatable, sp));
waitForSwing();
}
private AnnotatedTextFieldElement getAnnotatedTextFieldElement(FieldElement element) {
assertThat(element, instanceOf(CompositeFieldElement.class));
@ -795,6 +798,12 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
}
}
private void assertErrorDialog(String title) {
Window window = waitForWindowByTitleContaining(title);
runSwing(() -> window.setVisible(false));
waitForSwing(); // let post-dialog processing happen
}
//==================================================================================================
// Fake/Spy Classes
//==================================================================================================
@ -858,24 +867,20 @@ public class AnnotationTest extends AbstractGhidraHeadedIntegrationTest {
private List<TestDummyDomainFolder> folders = CollectionUtils.asList(this);
private List<TestDummyDomainFile> files =
private List<TestDummyDomainFile> folderFiles =
CollectionUtils.asList(new TestDummyDomainFile(this, OTHER_PROGRAM_NAME));
public FakeRootFolder() {
super(null, "Fake Root Folder");
}
void addFile(TestDummyDomainFile f) {
files.add(f);
}
void addFolder(TestDummyDomainFolder f) {
folders.add(f);
}
@Override
public synchronized DomainFile[] getFiles() {
return files.toArray(new TestDummyDomainFile[files.size()]);
return folderFiles.toArray(new TestDummyDomainFile[folderFiles.size()]);
}
@Override

View file

@ -28,7 +28,7 @@ import javax.swing.tree.TreePath;
import org.junit.*;
import docking.ActionContext;
import docking.*;
import docking.action.DockingActionIf;
import docking.action.ToggleDockingAction;
import docking.test.AbstractDockingTest;
@ -92,11 +92,11 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
@Test
public void testNewFolder() throws Exception {
final DockingActionIf newFolderAction = getAction("New Folder");
DockingActionIf newFolderAction = getAction("New Folder");
setSelectionPaths(new TreePath[] { rootNode.getTreePath() });
int count = rootNode.getChildCount();
performAction(newFolderAction, getDomainFileActionContext(), true);
SwingUtilities.invokeAndWait(() -> tree.stopEditing());
runSwing(() -> tree.stopEditing());
assertEquals(count + 1, rootNode.getChildCount());
assertNotNull(getChild(rootNode, "NewFolder"));
}
@ -104,11 +104,11 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
@Test
public void testNewFolderBlankName() throws Exception {
// try entering a blank name
final DockingActionIf newFolderAction = getAction("New Folder");
DockingActionIf newFolderAction = getAction("New Folder");
setSelectionPaths(new TreePath[] { rootNode.getTreePath() });
performAction(newFolderAction, getDomainFileActionContext(), true);
waitForTree();
SwingUtilities.invokeLater(() -> {
runSwingLater(() -> {
GTreeNode node = rootNode.getChild("NewFolder");
int row = tree.getRowForPath(node.getTreePath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
@ -123,10 +123,9 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
});
waitForSwing();
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
AbstractErrDialog d = waitForErrorDialog();
assertEquals("Rename Failed", d.getTitle());
pressButtonByText(d.getComponent(), "OK");
close(d);
}
@Test
@ -137,7 +136,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
setSelectionPaths(new TreePath[] { rootNode.getTreePath() });
performAction(newFolderAction, getDomainFileActionContext(), true);
waitForTree();
SwingUtilities.invokeAndWait(() -> tree.stopEditing());
runSwing(() -> tree.stopEditing());
waitForTree();
if (i > 0) {
assertNotNull(getChild(rootNode, "NewFolder" + (i + 1)));
@ -371,9 +370,9 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
rootFolder.createFolder("otherFolder");
waitForSwing();
final GTreeNode otherNode = getChild(rootNode, "otherFolder");
GTreeNode otherNode = getChild(rootNode, "otherFolder");
// drag myFolder to otherFolder
final GTreeNode myNode = getChild(rootNode, "myFolder");
GTreeNode myNode = getChild(rootNode, "myFolder");
doDrag(otherNode, DnDConstants.ACTION_MOVE, myNode);
@ -460,10 +459,9 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
doDrag(myNode, DnDConstants.ACTION_MOVE, npNode);
waitForTree();
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
AbstractErrDialog d = waitForErrorDialog();
assertEquals("Cannot Move File", d.getTitle());
pressButtonByText(d.getComponent(), "OK");
close(d);
expandTreePath(myNode.getTreePath());
assertEquals(0, myNode.getChildCount());
@ -535,7 +533,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
rootFolder.createFolder("myFolder");
waitForSwing();
final GTreeNode myNode = rootNode.getChild("myFolder");
GTreeNode myNode = rootNode.getChild("myFolder");
setSelectionPath(myNode.getTreePath());
DockingActionIf renameAction = getAction("Rename");
@ -543,7 +541,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
waitForTree();
// select "Rename" action
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
int row = tree.getRowForPath(myNode.getTreePath());
JTree jTree = (JTree) getInstanceField("tree", tree);
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
@ -561,7 +559,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
@Test
public void testRenameFile() throws Exception {
final GTreeNode npNode = rootNode.getChild("notepad");
GTreeNode npNode = rootNode.getChild("notepad");
setSelectionPath(npNode.getTreePath());
DockingActionIf renameAction = getAction("Rename");
@ -569,7 +567,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
waitForTree();
// select "Rename" action
SwingUtilities.invokeAndWait(() -> {
runSwing(() -> {
int row = tree.getRowForPath(npNode.getTreePath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
JTree jTree = (JTree) getInstanceField("tree", tree);
@ -588,7 +586,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
@Test
public void testRenameFileInUse() throws Exception {
final GTreeNode npNode = rootNode.getChild("notepad");
GTreeNode npNode = rootNode.getChild("notepad");
DomainFile df = ((DomainFileNode) npNode).getDomainFile();
setInUse(df);
@ -599,9 +597,9 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
executeOnSwingWithoutBlocking(
() -> performAction(renameAction, getDomainFileActionContext(), true));
waitForSwing();
OptionDialog dlg = waitForDialogComponent(OptionDialog.class);
assertEquals("Rename Not Allowed", dlg.getTitle());
pressButtonByText(dlg.getComponent(), "OK");
DialogComponentProvider d = waitForDialogComponent("Rename Not Allowed");
pressButtonByText(d.getComponent(), "OK");
assertNotNull(rootNode.getChild("notepad"));
}
@ -618,7 +616,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
DomainFile df = f.createFile("notepad", p, TaskMonitor.DUMMY);
waitForSwing();
final GTreeNode myNode = rootNode.getChild("myFolder");
GTreeNode myNode = rootNode.getChild("myFolder");
((DomainFolderNode) myNode).getDomainFolder().createFile("notepad", p, TaskMonitor.DUMMY);
p.release(this);
@ -630,12 +628,12 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
setSelectionPath(myNode.getTreePath());
final DockingActionIf renameAction = getAction("Rename");
DockingActionIf renameAction = getAction("Rename");
performAction(renameAction, getDomainFileActionContext(), true);
waitForTree();
// attempt to rename "myFolder"
SwingUtilities.invokeLater(() -> {
runSwingLater(() -> {
int row = tree.getRowForPath(myNode.getTreePath());
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
JTree jTree = (JTree) getInstanceField("tree", tree);
@ -649,10 +647,9 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
waitForSwing();
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
AbstractErrDialog d = waitForErrorDialog();
assertEquals("Rename Failed", d.getTitle());
pressButtonByText(d.getComponent(), "OK");
close(d);
assertNotNull(rootNode.getChild("myFolder"));
}
@ -756,7 +753,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
// Private Methods
//==================================================================================================
private void setSelectionPath(final TreePath path) throws Exception {
private void setSelectionPath(TreePath path) throws Exception {
tree.setSelectionPath(path);
waitForTree();
}
@ -802,7 +799,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
setInUse(df, "/notepad");
}
private void setInUse(DomainFile df, final String path) throws Exception {
private void setInUse(DomainFile df, String path) throws Exception {
ProgramDB program = createDefaultProgram("test1", ProgramBuilder._TOY, this);
//

View file

@ -41,10 +41,6 @@ public class CloseToolTest extends AbstractGhidraHeadedIntegrationTest {
private TestEnv env;
public CloseToolTest() {
super();
}
@Before
public void setUp() throws Exception {

View file

@ -105,7 +105,7 @@ public final class CryptoKeyFactory {
}
}
catch (Exception e) {
Msg.showWarn(CryptoKeyFactory.class, null, "Error Parsing Crypto Keys File",
Msg.showError(CryptoKeyFactory.class, null, "Error Parsing Crypto Keys File",
"Unable to process crypto keys files.", e);
}
}

View file

@ -29,17 +29,14 @@ import ghidra.program.model.symbol.*;
import ghidra.program.util.ProgramSelection;
public class DiffApplyIgnoreTest extends DiffApplyTestAdapter {
public DiffApplyIgnoreTest() {
super();
}
@Test
public void testProgramContextIgnore() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
assertNotNull(dialog);
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -54,10 +51,10 @@ public class DiffApplyIgnoreTest extends DiffApplyTestAdapter {
public void testByteIgnore() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
assertNotNull(dialog);
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -71,10 +68,10 @@ public class DiffApplyIgnoreTest extends DiffApplyTestAdapter {
@Test
public void testCodeUnitIgnore() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
assertNotNull(dialog);
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -88,10 +85,10 @@ public class DiffApplyIgnoreTest extends DiffApplyTestAdapter {
@Test
public void testReferenceIgnore() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
assertNotNull(dialog);
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
memRefIgnore();
@ -208,10 +205,10 @@ public class DiffApplyIgnoreTest extends DiffApplyTestAdapter {
@Test
public void testBookmarkIgnore() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
assertNotNull(dialog);
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -225,10 +222,10 @@ public class DiffApplyIgnoreTest extends DiffApplyTestAdapter {
@Test
public void testPropertyIgnore() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
assertNotNull(dialog);
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -242,10 +239,10 @@ public class DiffApplyIgnoreTest extends DiffApplyTestAdapter {
@Test
public void testFunctionIgnore() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
assertNotNull(dialog);
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();

View file

@ -15,8 +15,7 @@
*/
package ghidra.app.plugin.core.diff;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.util.*;
@ -36,14 +35,10 @@ import ghidra.util.exception.InvalidInputException;
public class DiffApplyReplaceTest extends DiffApplyTestAdapter {
public DiffApplyReplaceTest() {
super();
}
@Test
public void testProgramContextReplace() throws Exception {
openDiff(diffTestP1, diffTestP2);
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -57,9 +52,9 @@ public class DiffApplyReplaceTest extends DiffApplyTestAdapter {
@Test
public void testByteReplace() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -73,9 +68,9 @@ public class DiffApplyReplaceTest extends DiffApplyTestAdapter {
@Test
public void testCodeUnitReplace() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -89,9 +84,9 @@ public class DiffApplyReplaceTest extends DiffApplyTestAdapter {
@Test
public void testReferenceReplace() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
memRefReplace();
extRefReplace();
@ -284,9 +279,9 @@ public class DiffApplyReplaceTest extends DiffApplyTestAdapter {
@Test
public void testBookmarkReplace() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -300,9 +295,9 @@ public class DiffApplyReplaceTest extends DiffApplyTestAdapter {
@Test
public void testPropertyReplace() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();
@ -316,9 +311,9 @@ public class DiffApplyReplaceTest extends DiffApplyTestAdapter {
@Test
public void testFunctionReplace() throws Exception {
openDiff(diffTestP1, diffTestP2);
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Memory Differs", 2000);
JDialog dialog = waitForJDialog("Memory Differs");
pressButtonByText(dialog, "OK");
waitForPostedSwingRunnables();
waitForSwing();
showApplySettings();
ProgramSelection origDiffs = diffPlugin.getDiffHighlightSelection();

View file

@ -24,7 +24,6 @@ import javax.swing.*;
import org.junit.Before;
import org.junit.Test;
import docking.widgets.MultiLineLabel;
import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.AddressSet;
@ -353,9 +352,6 @@ public class DiffGetTest extends DiffTestAdapter {
assertNull(fp2.getTopLevelAncestor());
Window win = waitForWindow("Can't Open Selected Program");
assertNotNull(win);
String msg = findComponent(win, MultiLineLabel.class).getLabel();
assertTrue(msg.startsWith("Programs languages don't match."));
pressButton(win, "OK");
win = waitForWindow("Select Other Program");
assertNotNull(win);

View file

@ -147,9 +147,6 @@ public class DualProgramTest extends DiffTestAdapter {
waitForTasks();
win = waitForWindow("Can't Open Selected Program");
assertNotNull(win);
MultiLineLabel mll = findComponent(win, MultiLineLabel.class);
assertTrue(mll.getLabel().startsWith("Programs languages don't match."));
pressButton(win, "OK");
win = waitForWindow("Select Other Program");

View file

@ -24,7 +24,6 @@ import javax.swing.table.TableModel;
import org.junit.*;
import docking.widgets.MultiLineLabel;
import docking.wizard.WizardManager;
import docking.wizard.WizardPanel;
import generic.test.TestUtils;
@ -46,8 +45,8 @@ import ghidra.util.table.GhidraTable;
public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
private static final String TEST_SOURCE_PROGRAM_NAME = "VersionTracking/WallaceSrc";
private static final String TEST_DESTINATION_PROGRAM_NAME = "VersionTracking/WallaceVersion2";
private static String TEST_SOURCE_PROGRAM_NAME = "VersionTracking/WallaceSrc";
private static String TEST_DESTINATION_PROGRAM_NAME = "VersionTracking/WallaceVersion2";
private enum VTWizardPanelAction {
BACK, NEXT, FINISH, CANCEL;
@ -130,7 +129,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -186,7 +185,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -248,7 +247,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -310,7 +309,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -387,7 +386,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -451,7 +450,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -515,7 +514,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -592,7 +591,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -694,7 +693,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
createWizardManager();
SystemUtilities.runSwingLater(
runSwingLater(
() -> wizardManager.showWizard(controller.getParentComponent()));
waitForDialogComponent(WizardManager.class);
@ -725,12 +724,12 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
String msgContains = "Data Reference Match";
JDialog dialog = waitForJDialog("Version Tracking: Add To Session");
assertNotNull("Info dialog not found", dialog);
MultiLineLabel label = (MultiLineLabel) findComponentByName(dialog, "MESSAGE-COMPONENT");
assertNotNull("Expected server error dialog", label);
String message = getMessageText(dialog);
assertTrue("Expected Server Error message starting with: " + msgStart,
label.getLabel().startsWith(msgStart));
message.startsWith(msgStart));
assertTrue("Expected Server Error message containing: " + msgContains,
label.getLabel().contains(msgContains));
message.contains(msgContains));
pressButtonByText(dialog, "OK");
waitForSwing();
@ -747,17 +746,13 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("Number of matches", 0, vtMatchSet2.getMatchCount());
}
//********************************************
// Private Work/Validation methods.
//********************************************
private void chooseFromCorrelationPanel(final String correlatorName,
final VTWizardPanelAction wizardAction) {
private void chooseFromCorrelationPanel(String correlatorName,
VTWizardPanelAction wizardAction) {
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
assertNotNull(currentWizardPanel);
assertTrue(currentWizardPanel instanceof CorrelatorPanel);
final CorrelatorPanel correlatorPanel = (CorrelatorPanel) currentWizardPanel;
CorrelatorPanel correlatorPanel = (CorrelatorPanel) currentWizardPanel;
SystemUtilities.runSwingNow(() -> {
GhidraTable table = (GhidraTable) TestUtils.getInstanceField("table", correlatorPanel);
TableModel model = table.getModel();
@ -771,7 +766,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
private void changeCorrelatorOptionsPanel(Object correlatorOptionsObject,
final VTWizardPanelAction wizardAction) {
VTWizardPanelAction wizardAction) {
// Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
@ -837,7 +832,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
private void changeAddressSetOptionsPanel(boolean excludeAccepted, boolean limitAddressSets,
final VTWizardPanelAction wizardAction) {
VTWizardPanelAction wizardAction) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
@ -1002,22 +997,22 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
}
private void changeAddressSetViaListRemoveRange(final boolean isSource,
final AddressSetPanel addressSetPanel, final AddressSetView desiredAddressSet) {
private void changeAddressSetViaListRemoveRange(boolean isSource,
AddressSetPanel addressSetPanel, AddressSetView desiredAddressSet) {
ChooseAddressSetEditorPanel panel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", addressSetPanel);
assertNotNull(panel);
final JButton addRangeButton =
JButton addRangeButton =
(JButton) TestUtils.getInstanceField("addRangeButton", panel);
assertNotNull("Couldn't get button for adding address range.", addRangeButton);
JButton listRemoveRangeButton =
(JButton) TestUtils.getInstanceField("removeRangeButton", panel);
assertNotNull("Couldn't get button for removing address range for list selection.",
listRemoveRangeButton);
final JList list = (JList) TestUtils.getInstanceField("list", panel);
JList<?> list = (JList<?>) TestUtils.getInstanceField("list", panel);
SystemUtilities.runSwingNow(() -> {
ListModel model = list.getModel();
ListModel<?> model = list.getModel();
int size = model.getSize();
list.setSelectionInterval(0, size - 1);// Select all items in the list.
});
@ -1033,17 +1028,16 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
}
private void changeAddressSetViaSubtractDialog(final boolean isSource,
final AddressSetPanel addressSetPanel, final AddressSetView desiredAddressSet) {
private void changeAddressSetViaSubtractDialog(boolean isSource,
AddressSetPanel addressSetPanel, AddressSetView desiredAddressSet) {
ChooseAddressSetEditorPanel panel =
(ChooseAddressSetEditorPanel) TestUtils.getInstanceField("panel", addressSetPanel);
assertNotNull(panel);
final JButton addRangeButton =
JButton addRangeButton =
(JButton) TestUtils.getInstanceField("addRangeButton", panel);
final JButton subtractRangeButton =
JButton subtractRangeButton =
(JButton) TestUtils.getInstanceField("subtractRangeButton", panel);
JList list = (JList) TestUtils.getInstanceField("list", panel);
Runnable r = () -> subtractRangeButton.doClick();
runSwing(r, false);
@ -1057,11 +1051,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
}
private void enterAddressRange(final boolean isSource, final String buttonText,
final String minAddress, final String maxAddress) {
private void enterAddressRange(boolean isSource, String buttonText,
String minAddress, String maxAddress) {
final AddRemoveAddressRangeDialog addRemoveDialog =
env.waitForDialogComponent(AddRemoveAddressRangeDialog.class, 2000);
AddRemoveAddressRangeDialog addRemoveDialog =
waitForDialogComponent(AddRemoveAddressRangeDialog.class);
assertNotNull(addRemoveDialog);
waitForSwing();
@ -1069,20 +1063,20 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals((isSource ? "Source" : "Destination") + " Address Range",
addRemoveDialog.getTitle());
final AddressInput minAddressField =
AddressInput minAddressField =
(AddressInput) TestUtils.getInstanceField("minAddressField", addRemoveDialog);
assertNotNull(minAddressField);
SystemUtilities.runSwingLater(() -> {
runSwingLater(() -> {
Address address = isSource ? sourceAddress(minAddress) : destinationAddress(minAddress);
minAddressField.setAddress(address);
});
waitForSwing();
final AddressInput maxAddressField =
AddressInput maxAddressField =
(AddressInput) TestUtils.getInstanceField("maxAddressField", addRemoveDialog);
assertNotNull(maxAddressField);
SystemUtilities.runSwingLater(() -> {
runSwingLater(() -> {
Address address = isSource ? sourceAddress(maxAddress) : destinationAddress(maxAddress);
maxAddressField.setAddress(address);
});
@ -1093,11 +1087,11 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue("Dialog not closed after pressing: " + buttonText, !addRemoveDialog.isShowing());
}
private void enterAddressRange(final boolean isSource, final String buttonText,
final Address minAddress, final Address maxAddress) {
private void enterAddressRange(boolean isSource, String buttonText,
Address minAddress, Address maxAddress) {
final AddRemoveAddressRangeDialog addRemoveDialog =
env.waitForDialogComponent(AddRemoveAddressRangeDialog.class, 2000);
AddRemoveAddressRangeDialog addRemoveDialog =
waitForDialogComponent(AddRemoveAddressRangeDialog.class);
assertNotNull(addRemoveDialog);
waitForSwing();
@ -1105,18 +1099,18 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals((isSource ? "Source" : "Destination") + " Address Range",
addRemoveDialog.getTitle());
final AddressInput minAddressField =
AddressInput minAddressField =
(AddressInput) TestUtils.getInstanceField("minAddressField", addRemoveDialog);
assertNotNull(minAddressField);
SystemUtilities.runSwingLater(() -> minAddressField.setAddress(minAddress));
runSwingLater(() -> minAddressField.setAddress(minAddress));
waitForSwing();
final AddressInput maxAddressField =
AddressInput maxAddressField =
(AddressInput) TestUtils.getInstanceField("maxAddressField", addRemoveDialog);
assertNotNull(maxAddressField);
SystemUtilities.runSwingLater(() -> {
runSwingLater(() -> {
maxAddressField.setAddress(maxAddress);
});
@ -1133,7 +1127,7 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
}
private void changeAddressSetsPanel(AddressSetChoice sourceChoice,
AddressSetChoice destinationChoice, final VTWizardPanelAction wizardAction) {
AddressSetChoice destinationChoice, VTWizardPanelAction wizardAction) {
changeAddressSetChoices(sourceChoice, destinationChoice);
@ -1154,8 +1148,8 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
setSelectionInTool(destinationTool, destinationSelection);
}
private void checkSummaryPanel(final String labelString, final String summaryString,
final VTWizardPanelAction wizardAction) {
private void checkSummaryPanel(String labelString, String summaryString,
VTWizardPanelAction wizardAction) {
// Address Set Options Panel
WizardPanel currentWizardPanel = wizardManager.getCurrentWizardPanel();
@ -1174,7 +1168,8 @@ public class VTAddToSessionTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(labelString, labelText);
assertEquals(summaryString, summaryText);
SystemUtilities.runSwingNow(() -> invoke(wizardAction));
runSwingLater(() -> invoke(wizardAction));
waitForSwing();
}
private int getRowWithFieldValueInColumn(String string, TableModel model, int column) {

View file

@ -0,0 +1,58 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docking;
import utility.function.Callback;
/**
* A dialog that is meant to be extended for showing exceptions
*/
public abstract class AbstractErrDialog extends DialogComponentProvider {
// at some point, there are too many exceptions to show
protected static final int MAX_EXCEPTIONS = 100;
private static final String ERRORS_PREFIX = " (";
private static final String ERRORS_SUFFIX = " Errors)";
private Callback closedCallback = Callback.dummy();
protected AbstractErrDialog(String title) {
super(title, true, false, true, false);
}
@Override
protected final void dialogClosed() {
closedCallback.call();
}
/**
* Returns the string message of this error dialog
* @return the message
*/
public abstract String getMessage();
abstract void addException(String message, Throwable t);
abstract int getExceptionCount();
void updateTitle() {
setTitle(getTitle() + ERRORS_PREFIX + getExceptionCount() + ERRORS_SUFFIX);
}
void setClosedCallback(Callback callback) {
closedCallback = Callback.dummyIfNull(callback);
}
}

View file

@ -220,6 +220,12 @@ public class DockingDialog extends JDialog implements HelpDescriptor {
component.escapeCallback();
}
@Override
public void windowClosed(WindowEvent e) {
// this call is needed to handle the case where the dialog is closed by Java and
// not by the user closing the dialog or calling close() through the API
cleanup();
}
};
this.addWindowListener(windowAdapter);
modalFixWindowAdapter = new WindowAdapter() {
@ -249,6 +255,10 @@ public class DockingDialog extends JDialog implements HelpDescriptor {
}
void close() {
cleanup();
}
private void cleanup() {
if (component.getRemberSize() || component.getRememberLocation()) {
String key = getKey();
Rectangle rect = getBounds();
@ -258,7 +268,10 @@ public class DockingDialog extends JDialog implements HelpDescriptor {
component.setDialog(null);
removeWindowListener(windowAdapter);
// this will do nothing if already closed
setVisible(false);
component.dialogClosed();
component = null;
getContentPane().removeAll();

View file

@ -17,7 +17,6 @@ package docking;
import java.awt.Component;
import java.awt.Window;
import java.io.*;
import docking.widgets.OkDialog;
import docking.widgets.OptionDialog;
@ -26,7 +25,16 @@ import ghidra.util.exception.MultipleCauses;
public class DockingErrorDisplay implements ErrorDisplay {
private static final int TRACE_BUFFER_SIZE = 250;
/**
* Error dialog used to append exceptions.
*
* <p>While this dialog is showing all new exceptions will be added to the dialog. When
* this dialog is closed, this reference will be cleared.
*
* <p>Note: all use of this variable <b>must be on the Swing thread</b> to avoid thread
* visibility issues.
*/
private static AbstractErrDialog activeDialog;
ConsoleErrorDisplay consoleDisplay = new ConsoleErrorDisplay();
@ -52,8 +60,8 @@ public class DockingErrorDisplay implements ErrorDisplay {
private void displayMessage(MessageType messageType, ErrorLogger errorLogger, Object originator,
Component parent, String title, Object message, Throwable throwable) {
int dialogType = OptionDialog.PLAIN_MESSAGE;
int dialogType = OptionDialog.PLAIN_MESSAGE;
String messageString = message != null ? message.toString() : null;
String rawMessage = HTMLUtilities.fromHTML(messageString);
switch (messageType) {
@ -75,7 +83,7 @@ public class DockingErrorDisplay implements ErrorDisplay {
break;
}
showDialog(title, message, throwable, dialogType, messageString, getWindow(parent));
showDialog(title, throwable, dialogType, messageString, getWindow(parent));
}
private Component getWindow(Component component) {
@ -85,33 +93,45 @@ public class DockingErrorDisplay implements ErrorDisplay {
return component;
}
private void showDialog(final String title, final Object message, final Throwable throwable,
private void showDialog(final String title, final Throwable throwable,
final int dialogType, final String messageString, final Component parent) {
SystemUtilities.runIfSwingOrPostSwingLater(
() -> doShowDialog(title, message, throwable, dialogType, messageString, parent));
}
private void doShowDialog(final String title, final Object message, final Throwable throwable,
int dialogType, String messageString, Component parent) {
DialogComponentProvider dialog = null;
if (throwable != null) {
dialog = createErrorDialog(title, message, throwable, messageString);
if (dialogType == OptionDialog.ERROR_MESSAGE) {
// Note: all calls to manipulate the error dialog must be on the Swing thread to
// guarantee thread visibility to our state variables
Swing.runIfSwingOrRunLater(
() -> showDialogOnSwing(title, throwable, dialogType, messageString, parent));
}
else {
dialog = new OkDialog(title, messageString, dialogType);
DockingWindowManager.showDialog(parent,
new OkDialog(title, messageString, dialogType));
}
DockingWindowManager.showDialog(parent, dialog);
}
private DialogComponentProvider createErrorDialog(final String title, final Object message,
final Throwable throwable, String messageString) {
private void showDialogOnSwing(String title, Throwable throwable,
int dialogType, String messageString, Component parent) {
if (activeDialog != null) {
activeDialog.addException(messageString, throwable);
return;
}
activeDialog = createErrorDialog(title, throwable, messageString);
activeDialog.setClosedCallback(() -> {
activeDialog.setClosedCallback(null);
activeDialog = null;
});
DockingWindowManager.showDialog(parent, activeDialog);
}
private AbstractErrDialog createErrorDialog(String title, Throwable throwable,
String messageString) {
if (containsMultipleCauses(throwable)) {
return new ErrLogExpandableDialog(title, messageString, throwable);
}
return ErrLogDialog.createExceptionDialog(title, messageString,
buildStackTrace(throwable, message == null ? throwable.getMessage() : messageString));
return ErrLogDialog.createExceptionDialog(title, messageString, throwable);
}
private boolean containsMultipleCauses(Throwable throwable) {
@ -125,34 +145,4 @@ public class DockingErrorDisplay implements ErrorDisplay {
return containsMultipleCauses(throwable.getCause());
}
/**
* Build a displayable stack trace from a Throwable
*
* @param t the throwable
* @param msg message prefix
* @return multi-line stack trace
*/
private String buildStackTrace(Throwable t, String msg) {
StringBuffer sb = new StringBuffer(TRACE_BUFFER_SIZE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
if (msg != null) {
ps.println(msg);
}
t.printStackTrace(ps);
sb.append(baos.toString());
ps.close();
try {
baos.close();
}
catch (IOException e) {
// shouldn't happen--not really connected to the system
}
return sb.toString();
}
}

View file

@ -20,20 +20,35 @@ import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.*;
import docking.widgets.ScrollableTextArea;
import docking.widgets.label.GHtmlLabel;
import docking.widgets.label.GIconLabel;
import docking.widgets.table.*;
import generic.json.Json;
import generic.util.WindowUtilities;
import ghidra.docking.settings.Settings;
import ghidra.framework.Application;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.framework.plugintool.ServiceProviderStub;
import ghidra.util.HTMLUtilities;
import ghidra.util.Swing;
import ghidra.util.table.column.DefaultTimestampRenderer;
import ghidra.util.table.column.GColumnRenderer;
import utilities.util.reflection.ReflectionUtilities;
public class ErrLogDialog extends DialogComponentProvider {
private static final int TEXT_ROWS = 30;
/**
* A dialog that takes error text and displays it with an option details button. If there is
* an {@link ErrorReporter}, then a button is provided to report the error.
*/
public class ErrLogDialog extends AbstractErrDialog {
private static final int TEXT_ROWS = 20;
private static final int TEXT_COLUMNS = 80;
private static final int ERROR_BUFFER_SIZE = 1024;
private static final String SEND = "Log Error...";
private static final String DETAIL = "Details >>>";
@ -46,32 +61,30 @@ public class ErrLogDialog extends DialogComponentProvider {
/** tracks 'details panel' open state across invocations */
private static boolean isShowingDetails = false;
private int errorId = 0;
// state-dependent gui members
private ErrorDetailsPanel detailsPanel;
private ErrorDetailsSplitPane detailsPane;
private JButton detailsButton;
private JButton sendButton;
private JPanel mainPanel;
private static ErrorReporter errorReporter;
public static ErrLogDialog createExceptionDialog(String title, String message, String details) {
return new ErrLogDialog(title, message, details, true);
private List<ErrorEntry> errors = new ArrayList<>();
public static ErrLogDialog createExceptionDialog(String title, String message, Throwable t) {
return new ErrLogDialog(title, message, t);
}
public static ErrLogDialog createLogMessageDialog(String title, String message,
String details) {
return new ErrLogDialog(title, message, details, false);
}
private ErrLogDialog(String title, String message, Throwable throwable) {
super(title != null ? title : "Error");
ErrorEntry error = new ErrorEntry(message, throwable);
errors.add(error);
/**
* Constructor.
* Used by the Err class's static methods for logging various
* kinds of errors: Runtime, System, User, Asserts
*/
private ErrLogDialog(String title, String message, String details, boolean isException) {
super(title != null ? title : "Error", true, false, true, false);
setRememberSize(false);
setRememberLocation(false);
buildMainPanel(message, addUsefulReportingInfo(details), isException);
buildMainPanel(message);
}
private String addUsefulReportingInfo(String details) {
@ -127,13 +140,21 @@ public class ErrLogDialog extends DialogComponentProvider {
return errorReporter;
}
private void buildMainPanel(String message, String details, boolean isException) {
private void buildMainPanel(String message) {
JPanel introPanel = new JPanel(new BorderLayout(10, 10));
introPanel.add(
new GIconLabel(UIManager.getIcon("OptionPane.errorIcon"), SwingConstants.RIGHT),
BorderLayout.WEST);
introPanel.add(new GHtmlLabel(HTMLUtilities.toHTML(message)), BorderLayout.CENTER);
introPanel.add(new GHtmlLabel(HTMLUtilities.toHTML(message)) {
@Override
public Dimension getPreferredSize() {
// rendering HTML the label can expand larger than the screen; keep it reasonable
Dimension size = super.getPreferredSize();
size.width = 300;
return size;
}
}, BorderLayout.CENTER);
mainPanel = new JPanel(new BorderLayout(10, 20));
mainPanel.add(introPanel, BorderLayout.NORTH);
@ -141,21 +162,15 @@ public class ErrLogDialog extends DialogComponentProvider {
sendButton = new JButton(SEND);
sendButton.addActionListener(e -> sendDetails());
detailsPanel = new ErrorDetailsPanel();
detailsButton = new JButton(isShowingDetails ? CLOSE : DETAIL);
detailsButton.addActionListener(e -> {
String label = detailsButton.getText();
showDetails(label.equals(DETAIL));
});
if (isException) {
detailsPanel.setExceptionMessage(details);
}
else {
detailsPanel.setLogMessage(details);
}
detailsPane = new ErrorDetailsSplitPane();
JPanel buttonPanel = new JPanel(new GridLayout(2, 1, 5, 5));
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
if (errorReporter != null) {
buttonPanel.add(sendButton);
@ -163,16 +178,16 @@ public class ErrLogDialog extends DialogComponentProvider {
buttonPanel.add(detailsButton);
introPanel.add(buttonPanel, BorderLayout.EAST);
mainPanel.add(detailsPanel, BorderLayout.CENTER);
mainPanel.add(detailsPane, BorderLayout.CENTER);
addWorkPanel(mainPanel);
addOKButton();
setDefaultButton(okButton);
// show the details panel if it was showing previously
detailsPanel.setVisible(isShowingDetails);
// setHelpLocation(new HelpLocation(HelpTopics.INTRO, "Err"));
detailsPane.setVisible(isShowingDetails);
detailsPane.selectFirstError();
}
@Override
@ -185,82 +200,69 @@ public class ErrLogDialog extends DialogComponentProvider {
cancelCallback();
}
/**
* Send error details from dialog.
*/
private void sendDetails() {
String details = detailsPanel.getDetails();
String details = detailsPane.getDetails();
String title = getTitle();
close();
errorReporter.report(rootPanel, title, details);
}
/**
* opens and closes the details panel; used also by Err when
* showLog is called from SessionGui Help menu to show details
* when visible
*/
private void showDetails(boolean visible) {
isShowingDetails = visible;
String label = (visible ? CLOSE : DETAIL);
detailsButton.setText(label);
detailsPanel.setVisible(visible);
detailsPane.setVisible(visible);
repack(); // need to re-pack so the detailsPanel can be hidden correctly
}
// custom "pack" so the detailsPanel can be shown/hidden correctly
@Override
protected void repack() {
// hide the dialog so that the user doesn't see us resize and then move it, which looks
// awkward
getDialog().setVisible(false);
detailsPanel.invalidate(); // force to be invalid so resizes correctly
rootPanel.validate();
super.repack();
// center the dialog after its size changes for a cleaner appearance
DockingDialog dialog = getDialog();
Container parent = dialog.getParent();
Point centerPoint = WindowUtilities.centerOnComponent(parent, dialog);
dialog.setLocation(centerPoint);
getDialog().setVisible(true);
public String getMessage() {
return detailsPane.getMessage();
}
@Override
protected void dialogShown() {
// TODO test that the parent DockingDialog code handles this....
WindowUtilities.ensureOnScreen(getDialog());
Swing.runLater(() -> okButton.requestFocusInWindow());
}
/**
* scrolled text panel used to display the error message details;
* each time an error message is "added", appends the contents to
* the internal StringBuffer.
*/
private class ErrorDetailsPanel extends JPanel {
private ScrollableTextArea textDetails;
private StringBuffer errorDetailsBuffer;
private Dimension closedSize;
@Override
void addException(String message, Throwable t) {
int n = errors.size();
if (n > MAX_EXCEPTIONS) {
return;
}
errors.add(new ErrorEntry(message, t));
detailsPane.update();
updateTitle(); // signal the new error
}
@Override
int getExceptionCount() {
return errors.size();
}
private class ErrorDetailsSplitPane extends JSplitPane {
private final double TOP_PREFERRED_RESIZE_WEIGHT = .80;
private ErrorDetailsPanel detailsPanel;
private ErrorDetailsTablePanel tablePanel;
private Dimension openedSize;
private ErrorDetailsPanel() {
super(new BorderLayout(0, 0));
errorDetailsBuffer = new StringBuffer(ERROR_BUFFER_SIZE);
textDetails = new ScrollableTextArea(TEXT_ROWS, TEXT_COLUMNS);
textDetails.setEditable(false);
add(textDetails, BorderLayout.CENTER);
validate();
textDetails.scrollToBottom();
ErrorDetailsSplitPane() {
super(VERTICAL_SPLIT);
setResizeWeight(TOP_PREFERRED_RESIZE_WEIGHT);
// set the initial preferred size of this panel
// when "closed"
Rectangle bounds = getBounds();
closedSize = new Dimension(bounds.width, 0);
detailsPanel = new ErrorDetailsPanel();
tablePanel = new ErrorDetailsTablePanel();
setTopComponent(detailsPanel);
setBottomComponent(tablePanel);
addComponentListener(new ComponentAdapter() {
@Override
@ -269,51 +271,283 @@ public class ErrLogDialog extends DialogComponentProvider {
return;
}
Rectangle localBounds = getBounds();
if (detailsButton.getText().equals(DETAIL)) {
closedSize.width = localBounds.width;
}
else {
if (!detailsButton.getText().equals(DETAIL)) {
openedSize = new Dimension(localBounds.width, localBounds.height);
}
}
});
}
void selectFirstError() {
tablePanel.selectFirstError();
}
String getDetails() {
return detailsPanel.getDetails();
}
String getMessage() {
return detailsPanel.getMessage();
}
void setError(ErrorEntry err) {
detailsPanel.setError(err);
}
void update() {
tablePanel.update();
}
@Override
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
if (detailsButton.getText().equals(DETAIL)) {
return closedSize;
return superSize;
}
if (openedSize == null) {
return super.getPreferredSize();
return superSize;
}
return openedSize;
}
}
/**
* resets the current error buffer to the contents of msg
*/
private void setLogMessage(String msg) {
errorDetailsBuffer = new StringBuffer(msg);
textDetails.setText(msg);
private class ErrorDetailsTablePanel extends JPanel {
// scroll to bottom so user is viewing the last message
private ErrEntryTableModel model;
private GTable errorsTable;
private GTableFilterPanel<ErrorEntry> tableFilterPanel;
ErrorDetailsTablePanel() {
setLayout(new BorderLayout());
model = new ErrEntryTableModel();
errorsTable = new GTable(model);
tableFilterPanel = new GTableFilterPanel<ErrorEntry>(errorsTable, model);
errorsTable.getSelectionManager().addListSelectionListener(e -> {
if (e.getValueIsAdjusting()) {
return;
}
int firstIndex = errorsTable.getSelectedRow();
if (firstIndex == -1) {
return;
}
ErrorEntry err = tableFilterPanel.getRowObject(firstIndex);
detailsPane.setError(err);
});
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.add(new JScrollPane(errorsTable), BorderLayout.CENTER);
tablePanel.add(tableFilterPanel, BorderLayout.SOUTH);
add(tablePanel, BorderLayout.CENTER);
// initialize this value to something small so the full dialog will not consume the
// entire screen height
setPreferredSize(new Dimension(400, 100));
}
void selectFirstError() {
errorsTable.selectRow(0);
}
void update() {
model.fireTableDataChanged();
}
}
/**
* scrolled text panel used to display the error message details;
* each time an error message is "added", appends the contents to
* the internal StringBuffer.
*/
private class ErrorDetailsPanel extends JPanel {
private ScrollableTextArea textDetails;
private ErrorEntry error;
private ErrorDetailsPanel() {
super(new BorderLayout(0, 0));
textDetails = new ScrollableTextArea(TEXT_ROWS, TEXT_COLUMNS);
textDetails.setEditable(false);
add(textDetails, BorderLayout.CENTER);
validate();
textDetails.scrollToBottom();
}
private void setExceptionMessage(String msg) {
errorDetailsBuffer = new StringBuffer(msg);
textDetails.setText(msg);
void setError(ErrorEntry e) {
error = e;
setExceptionMessage(e.getDetailsText());
}
private void setExceptionMessage(String message) {
String updated = addUsefulReportingInfo(message);
textDetails.setText(updated);
// scroll to the top the see the pertinent part of the exception
textDetails.scrollToTop();
}
private final String getDetails() {
return errorDetailsBuffer.toString();
String getDetails() {
return textDetails.getText();
}
String getMessage() {
return error.getMessage();
}
}
private class ErrorEntry {
private String message;
private String details;
private Date timestamp = new Date();
private int myId = ++errorId;
ErrorEntry(String message, Throwable t) {
String updated = message;
if (HTMLUtilities.isHTML(updated)) {
updated = HTMLUtilities.fromHTML(updated);
}
this.message = updated;
if (t != null) {
this.details = ReflectionUtilities.stackTraceToString(t);
}
}
int getId() {
return myId;
}
String getMessage() {
return message;
}
Date getTimestamp() {
return timestamp;
}
String getDetailsText() {
if (details == null) {
return message;
}
return details;
}
String getDetails() {
return details;
}
@Override
public String toString() {
return Json.toString(this);
}
}
private class ErrEntryTableModel extends GDynamicColumnTableModel<ErrorEntry, Object> {
public ErrEntryTableModel() {
super(new ServiceProviderStub());
}
@Override
protected TableColumnDescriptor<ErrorEntry> createTableColumnDescriptor() {
TableColumnDescriptor<ErrorEntry> descriptor = new TableColumnDescriptor<ErrorEntry>();
descriptor.addVisibleColumn(new IdColumn(), 1, true);
descriptor.addVisibleColumn(new MessageColumn());
descriptor.addHiddenColumn(new DetailsColumn());
descriptor.addVisibleColumn(new TimestampColumn());
return descriptor;
}
@Override
public String getName() {
return "Unexpectd Errors";
}
@Override
public List<ErrorEntry> getModelData() {
return errors;
}
@Override
public Object getDataSource() {
return null;
}
private class IdColumn extends AbstractDynamicTableColumnStub<ErrorEntry, Integer> {
@Override
public Integer getValue(ErrorEntry rowObject, Settings settings, ServiceProvider sp)
throws IllegalArgumentException {
return rowObject.getId();
}
@Override
public String getColumnName() {
return "#";
}
@Override
public int getColumnPreferredWidth() {
return 40;
}
}
private class MessageColumn extends AbstractDynamicTableColumnStub<ErrorEntry, String> {
@Override
public String getValue(ErrorEntry rowObject, Settings settings, ServiceProvider sp)
throws IllegalArgumentException {
return rowObject.getMessage();
}
@Override
public String getColumnName() {
return "Message";
}
}
private class DetailsColumn extends AbstractDynamicTableColumnStub<ErrorEntry, String> {
@Override
public String getValue(ErrorEntry rowObject, Settings settings, ServiceProvider sp)
throws IllegalArgumentException {
return rowObject.getDetails();
}
@Override
public String getColumnName() {
return "Details";
}
}
private class TimestampColumn extends AbstractDynamicTableColumnStub<ErrorEntry, Date> {
private GColumnRenderer<Date> renderer = new DefaultTimestampRenderer();
@Override
public Date getValue(ErrorEntry rowObject, Settings settings, ServiceProvider sp)
throws IllegalArgumentException {
return rowObject.getTimestamp();
}
@Override
public String getColumnName() {
return "Time";
}
@Override
public GColumnRenderer<Date> getColumnRenderer() {
return renderer;
}
}
}
}

View file

@ -32,12 +32,12 @@ import docking.widgets.label.GHtmlLabel;
import docking.widgets.tree.*;
import docking.widgets.tree.support.GTreeDragNDropHandler;
import ghidra.util.*;
import ghidra.util.exception.*;
import ghidra.util.exception.MultipleCauses;
import ghidra.util.html.HTMLElement;
import resources.ResourceManager;
import util.CollectionUtils;
public class ErrLogExpandableDialog extends DialogComponentProvider {
public class ErrLogExpandableDialog extends AbstractErrDialog {
public static ImageIcon IMG_REPORT = ResourceManager.loadImage("images/report.png");
public static ImageIcon IMG_EXCEPTION = ResourceManager.loadImage("images/exception.png");
public static ImageIcon IMG_FRAME_ELEMENT =
@ -53,113 +53,21 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
private static boolean showingDetails = false;
protected ReportRootNode root;
protected GTree excTree;
protected GTree tree;
private List<Throwable> errors = new ArrayList<>();
/** This spacer addresses the optical impression that the message panel changes size when showing details */
protected Component horizontalSpacer;
protected JButton detailButton;
protected JButton sendButton;
protected boolean hasConsole = false;
protected JPopupMenu popup;
protected static class ExcTreeTransferHandler extends TransferHandler
implements GTreeDragNDropHandler {
protected ErrLogExpandableDialog(String title, String msg, Throwable throwable) {
super(title);
protected ReportRootNode root;
errors.add(throwable);
public ExcTreeTransferHandler(ReportRootNode root) {
this.root = root;
}
@Override
public DataFlavor[] getSupportedDataFlavors(List<GTreeNode> transferNodes) {
return new DataFlavor[] { DataFlavor.stringFlavor };
}
@Override
protected Transferable createTransferable(JComponent c) {
ArrayList<GTreeNode> nodes = new ArrayList<>();
for (TreePath path : ((JTree) c).getSelectionPaths()) {
nodes.add((GTreeNode) path.getLastPathComponent());
}
try {
return new StringSelection(
(String) getTransferData(nodes, DataFlavor.stringFlavor));
}
catch (UnsupportedFlavorException e) {
Msg.debug(this, e.getMessage(), e);
}
return null;
}
@Override
public Object getTransferData(List<GTreeNode> transferNodes, DataFlavor flavor)
throws UnsupportedFlavorException {
if (flavor != DataFlavor.stringFlavor) {
throw new UnsupportedFlavorException(flavor);
}
if (transferNodes.isEmpty()) {
return null;
}
if (transferNodes.size() == 1) {
GTreeNode node = transferNodes.get(0);
if (node instanceof NodeWithText) {
return ((NodeWithText) node).collectReportText(transferNodes, 0).trim();
}
return null;
}
return root.collectReportText(transferNodes, 0).trim();
}
@Override
public boolean isStartDragOk(List<GTreeNode> dragUserData, int dragAction) {
for (GTreeNode node : dragUserData) {
if (node instanceof NodeWithText) {
return true;
}
}
return false;
}
@Override
public int getSupportedDragActions() {
return DnDConstants.ACTION_COPY;
}
@Override
public int getSourceActions(JComponent c) {
return COPY;
}
@Override
public boolean isDropSiteOk(GTreeNode destUserData, DataFlavor[] flavors, int dropAction) {
return false;
}
@Override
public void drop(GTreeNode destUserData, Transferable transferable, int dropAction) {
throw new UnsupportedOperationException();
}
}
public ErrLogExpandableDialog(String title, String msg, MultipleCauses mc) {
this(title, msg, mc.getCauses(), null, true, true);
}
public ErrLogExpandableDialog(String title, String msg, Throwable exc) {
this(title, msg, Collections.singletonList(exc), HasConsoleText.Util.get(exc), true, true);
}
public ErrLogExpandableDialog(String title, String msg, Collection<Throwable> report) {
this(title, msg, report, null, false, false);
}
protected ErrLogExpandableDialog(String title, String msg, Collection<Throwable> report,
String console, boolean modal, boolean hasDismiss) {
super(title, modal);
hasConsole = console != null;
popup = new JPopupMenu();
JMenuItem menuCopy = new JMenuItem("Copy");
menuCopy.setActionCommand((String) TransferHandler.getCopyAction().getValue(Action.NAME));
@ -173,13 +81,12 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
msgPanel.setLayout(new BorderLayout(16, 16));
msgPanel.setBorder(new EmptyBorder(16, 16, 16, 16));
{
JLabel msgText = new GHtmlLabel(getHTML(msg, report)) {
JLabel msgText = new GHtmlLabel(getHTML(msg, CollectionUtils.asSet(throwable))) {
@Override
public Dimension getPreferredSize() {
// when rendering HTML the label can expand larger than the screen;
// keep it reasonable
// rendering HTML the label can expand larger than the screen; keep it reasonable
Dimension size = super.getPreferredSize();
size.width = 500;
size.width = 300;
return size;
}
};
@ -206,7 +113,7 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
msgPanel.add(buttonBox, BorderLayout.EAST);
horizontalSpacer = Box.createVerticalStrut(10);
horizontalSpacer.setVisible(showingDetails | hasConsole);
horizontalSpacer.setVisible(showingDetails);
msgPanel.add(horizontalSpacer, BorderLayout.SOUTH);
}
workPanel.add(msgPanel, BorderLayout.NORTH);
@ -214,29 +121,8 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
Box workBox = Box.createVerticalBox();
{
if (hasConsole) {
JTextArea consoleText = new JTextArea(console);
JScrollPane consoleScroll =
new JScrollPane(consoleText, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED) {
@Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
dim.height = 400;
dim.width = 800; // trial and error?
return dim;
}
};
consoleText.setEditable(false);
consoleText.setBackground(Color.BLACK);
consoleText.setForeground(Color.WHITE);
consoleText.setFont(Font.decode("Monospaced"));
workBox.add(consoleScroll);
}
root = new ReportRootNode(getTitle(), report);
excTree = new GTree(root) {
root = new ReportRootNode(getTitle(), CollectionUtils.asSet(throwable));
tree = new GTree(root) {
@Override
public Dimension getPreferredSize() {
@ -249,19 +135,19 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
for (GTreeNode node : CollectionUtils.asIterable(root.iterator(true))) {
if (node instanceof ReportExceptionNode) {
excTree.expandTree(node);
tree.expandTree(node);
}
}
excTree.setSelectedNode(root.getChild(0));
excTree.setVisible(showingDetails);
tree.setSelectedNode(root.getChild(0));
tree.setVisible(showingDetails);
ExcTreeTransferHandler handler = new ExcTreeTransferHandler(root);
excTree.setDragNDropHandler(handler);
excTree.setTransferHandler(handler);
ActionMap map = excTree.getActionMap();
tree.setDragNDropHandler(handler);
tree.setTransferHandler(handler);
ActionMap map = tree.getActionMap();
map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
TransferHandler.getCopyAction());
excTree.addMouseListener(new MouseAdapter() {
tree.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
@ -279,22 +165,19 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
}
});
workBox.add(excTree);
workBox.add(tree);
}
workPanel.add(workBox, BorderLayout.CENTER);
repack();
addWorkPanel(workPanel);
if (hasDismiss) {
addDismissButton();
}
addDismissButton();
}
private String getHTML(String msg, Collection<Throwable> report) {
//
// TODO
// Usage question: The content herein will be escaped unless you call addHTMLContenet().
// Further, clients can provide messages that contain HTML. Is there a
// use case where we want to show escaped HTML content?
@ -332,14 +215,6 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
String htmlTMsg = addBR(tMsg);
body.addElement("p").addHTMLContent(htmlTMsg);
if (t instanceof CausesImportant) { // I choose not to recurse
HTMLElement ul = body.addElement("ul");
for (Throwable ts : MultipleCauses.Util.iterCauses(t)) {
String tsMsg = getMessage(ts);
String htmlTSMsg = addBR(tsMsg);
ul.addElement("li").addHTMLContent(htmlTSMsg);
}
}
}
return html.toString();
}
@ -357,15 +232,15 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
return t.getClass().getSimpleName();
}
void detailCallback() {
private void detailCallback() {
showingDetails = !showingDetails;
excTree.setVisible(showingDetails);
horizontalSpacer.setVisible(showingDetails | hasConsole);
tree.setVisible(showingDetails);
horizontalSpacer.setVisible(showingDetails);
detailButton.setText(showingDetails ? CLOSE : DETAIL);
repack();
}
void sendCallback() {
private void sendCallback() {
String details = root.collectReportText(null, 0).trim();
String title = getTitle();
close();
@ -379,6 +254,29 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
return dim;
}
@Override
public void addException(String message, Throwable t) {
int n = errors.size();
if (n > MAX_EXCEPTIONS) {
return;
}
errors.add(t);
root.addNode(new ReportExceptionNode(t));
updateTitle(); // signal the new error
}
@Override
int getExceptionCount() {
return root.getChildCount();
}
@Override
public String getMessage() {
return root.getReportText();
}
static interface NodeWithText {
public String getReportText();
@ -528,9 +426,6 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
@Override
public String getReportText() {
if (exc instanceof HasConsoleText) {
return getName() + "\n" + HasConsoleText.Util.get(exc);
}
return getName();
}
@ -661,6 +556,87 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
return false;
}
}
private static class ExcTreeTransferHandler extends TransferHandler
implements GTreeDragNDropHandler {
protected ReportRootNode root;
public ExcTreeTransferHandler(ReportRootNode root) {
this.root = root;
}
@Override
public DataFlavor[] getSupportedDataFlavors(List<GTreeNode> transferNodes) {
return new DataFlavor[] { DataFlavor.stringFlavor };
}
@Override
protected Transferable createTransferable(JComponent c) {
ArrayList<GTreeNode> nodes = new ArrayList<>();
for (TreePath path : ((JTree) c).getSelectionPaths()) {
nodes.add((GTreeNode) path.getLastPathComponent());
}
try {
return new StringSelection(
(String) getTransferData(nodes, DataFlavor.stringFlavor));
}
catch (UnsupportedFlavorException e) {
Msg.debug(this, e.getMessage(), e);
}
return null;
}
@Override
public Object getTransferData(List<GTreeNode> transferNodes, DataFlavor flavor)
throws UnsupportedFlavorException {
if (flavor != DataFlavor.stringFlavor) {
throw new UnsupportedFlavorException(flavor);
}
if (transferNodes.isEmpty()) {
return null;
}
if (transferNodes.size() == 1) {
GTreeNode node = transferNodes.get(0);
if (node instanceof NodeWithText) {
return ((NodeWithText) node).collectReportText(transferNodes, 0).trim();
}
return null;
}
return root.collectReportText(transferNodes, 0).trim();
}
@Override
public boolean isStartDragOk(List<GTreeNode> dragUserData, int dragAction) {
for (GTreeNode node : dragUserData) {
if (node instanceof NodeWithText) {
return true;
}
}
return false;
}
@Override
public int getSupportedDragActions() {
return DnDConstants.ACTION_COPY;
}
@Override
public int getSourceActions(JComponent c) {
return COPY;
}
@Override
public boolean isDropSiteOk(GTreeNode destUserData, DataFlavor[] flavors, int dropAction) {
return false;
}
@Override
public void drop(GTreeNode destUserData, Transferable transferable, int dropAction) {
throw new UnsupportedOperationException();
}
}
}
class TransferActionListener implements ActionListener, PropertyChangeListener {

View file

@ -15,78 +15,29 @@
*/
package docking.test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.*;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.*;
import docking.ActionContext;
import docking.ComponentPlaceholder;
import docking.ComponentProvider;
import docking.DialogComponentProvider;
import docking.DockableComponent;
import docking.DockingDialog;
import docking.DockingErrorDisplay;
import docking.DockingWindowManager;
import docking.EmptyBorderToggleButton;
import docking.Tool;
import docking.*;
import docking.action.DockingActionIf;
import docking.action.ToggleDockingActionIf;
import docking.actions.DockingToolActions;
@ -104,9 +55,7 @@ import generic.test.ConcurrentTestExceptionHandler;
import generic.util.image.ImageUtils;
import ghidra.GhidraTestApplicationLayout;
import ghidra.framework.ApplicationConfiguration;
import ghidra.util.ConsoleErrorDisplay;
import ghidra.util.ErrorDisplay;
import ghidra.util.Msg;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
import ghidra.util.task.SwingUpdateManager;
import ghidra.util.worker.Worker;
@ -209,7 +158,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
Iterator<Window> iter = winList.iterator();
while (iter.hasNext()) {
Window w = iter.next();
if (!w.isVisible()) {
if (!w.isShowing()) {
continue;
}
String titleForWindow = getTitleForWindow(w);
@ -229,7 +178,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
Iterator<Window> iter = winList.iterator();
while (iter.hasNext()) {
Window w = iter.next();
if (!w.isVisible()) {
if (!w.isShowing()) {
continue;
}
String titleForWindow = getTitleForWindow(w);
@ -240,6 +189,14 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
return null;
}
/**
* Waits for the system error dialog to appear
* @return the dialog
*/
public static AbstractErrDialog waitForErrorDialog() {
return waitForDialogComponent(AbstractErrDialog.class);
}
public static Window waitForWindow(Class<?> windowClass) {
if ((!Dialog.class.isAssignableFrom(windowClass)) &&
@ -256,7 +213,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
Iterator<Window> it = winList.iterator();
while (it.hasNext()) {
Window w = it.next();
if (windowClass.isAssignableFrom(w.getClass()) && w.isVisible()) {
if (windowClass.isAssignableFrom(w.getClass()) && w.isShowing()) {
return w;
}
}
@ -346,7 +303,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
Set<Window> allWindows = getAllWindows();
for (Window window : allWindows) {
String windowName = window.getName();
if (name.equals(windowName) && window.isVisible()) {
if (name.equals(windowName) && window.isShowing()) {
return window;
}
@ -358,13 +315,12 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
}
/**
* Check for and display message component text associated with
* ErrLogDialog and OptionDialog windows.
* Check for and display message component text associated with OptionDialog windows
* @param w any window
* @return the message string if one can be found; <code>null</code> otherwise
*/
public static String checkMessageDisplay(Window w) {
Component c = findComponentByName(w, "MESSAGE-COMPONENT");
public static String getMessageText(Window w) {
Component c = findComponentByName(w, OptionDialog.MESSAGE_COMPONENT_NAME);
if (c instanceof JLabel) {
return ((JLabel) c).getText();
}
@ -466,7 +422,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
// note: we use System.err here to get more obvious errors in the console
String title = getDebugTitleForWindow(window);
System.err.println("DockingTestCase - Forced window closure: " + title);
String errorMessage = checkMessageDisplay(window);
String errorMessage = getMessageText(window);
if (errorMessage != null) {
System.err.println("\tWindow error message: " + errorMessage);
}
@ -541,7 +497,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
Iterator<Window> iter = winList.iterator();
while (iter.hasNext()) {
Window w = iter.next();
if ((w instanceof JDialog) && w.isVisible()) {
if ((w instanceof JDialog) && w.isShowing()) {
String windowTitle = getTitleForWindow(w);
if (title.equals(windowTitle)) {
return (JDialog) w;
@ -576,7 +532,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
Iterator<Window> iter = winList.iterator();
while (iter.hasNext()) {
Window w = iter.next();
if ((w instanceof JDialog) && w.isVisible()) {
if ((w instanceof JDialog) && w.isShowing()) {
String windowTitle = getTitleForWindow(w);
if (title.equals(windowTitle)) {
return (JDialog) w;
@ -722,10 +678,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
return null;
}
if (!window.isVisible()) {
return null;
}
if (!window.isShowing()) {
return null;
}
@ -1132,8 +1084,10 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
public static Set<DockingActionIf> getActionsByOwnerAndName(Tool tool, String owner,
String name) {
Set<DockingActionIf> ownerActions = tool.getDockingActionsByOwnerName(owner);
return ownerActions.stream().filter(action -> action.getName().equals(name)).collect(
Collectors.toSet());
return ownerActions.stream()
.filter(action -> action.getName().equals(name))
.collect(
Collectors.toSet());
}
/**

View file

@ -99,7 +99,7 @@ import ghidra.util.exception.AssertException;
* @see OptionDialogBuilder
*/
public class OptionDialog extends DialogComponentProvider {
private static final String MESSAGE_COMPONENT_NAME = "MESSAGE-COMPONENT";
public static final String MESSAGE_COMPONENT_NAME = "MESSAGE-COMPONENT";
/** Used for error messages. */
public static final int ERROR_MESSAGE = 0;
/** Used for information messages. */

View file

@ -102,7 +102,7 @@ public class ScrollableTextArea extends JScrollPane {
}
/**
* Appends the text to the text area maintained in this scrollpane
* Appends the text to the text area maintained in this scroll pane
* @param text the text to append.
*/
public void append(String text) {
@ -111,13 +111,15 @@ public class ScrollableTextArea extends JScrollPane {
/**
* Returns the number of lines current set in the text area
* @return the count
*/
public int getLineCount() {
return textArea.getLineCount();
}
/**
* Returns the tabsize set in the text area
* Returns the tab size set in the text area
* @return the size
*/
public int getTabSize() {
return textArea.getTabSize();
@ -125,6 +127,7 @@ public class ScrollableTextArea extends JScrollPane {
/**
* Returns the total area height of the text area (row height * line count)
* @return the height
*/
public int getTextAreaHeight() {
return (textArea.getAreaHeight());
@ -132,6 +135,7 @@ public class ScrollableTextArea extends JScrollPane {
/**
* Returns the visible height of the text area
* @return the height
*/
public int getTextVisibleHeight() {
return textArea.getVisibleHeight();
@ -200,6 +204,7 @@ public class ScrollableTextArea extends JScrollPane {
/**
* Returns the text contained within the text area
* @return the text
*/
public String getText() {
return textArea.getText();

View file

@ -0,0 +1,55 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.util.table.column;
import java.awt.Component;
import java.util.Date;
import javax.swing.JLabel;
import docking.widgets.table.GTableCellRenderingData;
import ghidra.docking.settings.Settings;
import ghidra.util.DateUtils;
/**
* A renderer for clients that wish to display a {@link Date} as a timestamp with the
* date and time.
*/
public class DefaultTimestampRenderer extends AbstractGColumnRenderer<Date> {
@Override
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
JLabel label = (JLabel) super.getTableCellRendererComponent(data);
Date value = (Date) data.getValue();
if (value != null) {
label.setText(DateUtils.formatDateTimestamp(value));
}
return label;
}
@Override
public String getFilterString(Date t, Settings settings) {
return DateUtils.formatDateTimestamp(t);
}
@Override
public ColumnConstraintFilterMode getColumnConstraintFilterMode() {
// This allows for text filtering in the table and date filtering on columns
return ColumnConstraintFilterMode.ALLOW_ALL_FILTERS;
}
}

View file

@ -35,7 +35,7 @@ public class DockingErrorDisplayTest extends AbstractDockingTest {
DockingErrorDisplay display = new DockingErrorDisplay();
DefaultErrorLogger logger = new DefaultErrorLogger();
Exception exception = new Exception("My test exception");
doDisplay(display, logger, exception);
reportException(display, logger, exception);
assertErrLogDialog();
}
@ -46,11 +46,29 @@ public class DockingErrorDisplayTest extends AbstractDockingTest {
DefaultErrorLogger logger = new DefaultErrorLogger();
Exception nestedException = new Exception("My nested test exception");
Exception exception = new Exception("My test exception", nestedException);
doDisplay(display, logger, exception);
reportException(display, logger, exception);
assertErrLogDialog();
}
@Test
public void testDefaultErrorDisplay_MultipleAsynchronousExceptions() {
DockingErrorDisplay display = new DockingErrorDisplay();
DefaultErrorLogger logger = new DefaultErrorLogger();
Exception exception = new Exception("My test exception");
reportException(display, logger, exception);
ErrLogDialog dialog = getErrLogDialog();
assertExceptionCount(dialog, 1);
reportException(display, logger, new NullPointerException("It is null!"));
assertExceptionCount(dialog, 2);
close(dialog);
}
@Test
public void testMultipleCausesErrorDisplay() {
DockingErrorDisplay display = new DockingErrorDisplay();
@ -58,43 +76,51 @@ public class DockingErrorDisplayTest extends AbstractDockingTest {
Throwable firstCause = new Exception("My test exception - first cause");
MultipleCauses exception = new MultipleCauses(Collections.singletonList(firstCause));
doDisplay(display, logger, exception);
reportException(display, logger, exception);
assertErrLogExpandableDialog();
ErrLogExpandableDialog dialog = assertErrLogExpandableDialog();
assertExceptionCount(dialog, 1);
reportException(display, logger, new NullPointerException("It is null!"));
assertExceptionCount(dialog, 2);
close(dialog);
}
private void assertErrLogExpandableDialog() {
Window w = waitForWindow(TEST_TITLE, 2000);
assertNotNull(w);
private void assertExceptionCount(AbstractErrDialog errDialog, int n) {
final ErrLogExpandableDialog errDialog =
int actual = errDialog.getExceptionCount();
assertEquals(n, actual);
}
private ErrLogExpandableDialog assertErrLogExpandableDialog() {
Window w = waitForWindow(TEST_TITLE);
ErrLogExpandableDialog errDialog =
getDialogComponentProvider(w, ErrLogExpandableDialog.class);
assertNotNull(errDialog);
runSwing(new Runnable() {
@Override
public void run() {
errDialog.close();
}
});
return errDialog;
}
private void assertErrLogDialog() {
Window w = waitForWindow(TEST_TITLE, 2000);
Window w = waitForWindow(TEST_TITLE);
assertNotNull(w);
final ErrLogDialog errDialog = getDialogComponentProvider(w, ErrLogDialog.class);
ErrLogDialog errDialog = getDialogComponentProvider(w, ErrLogDialog.class);
assertNotNull(errDialog);
runSwing(new Runnable() {
@Override
public void run() {
errDialog.close();
}
});
close(errDialog);
}
private void doDisplay(final DockingErrorDisplay display, final DefaultErrorLogger logger,
private ErrLogDialog getErrLogDialog() {
Window w = waitForWindow(TEST_TITLE);
assertNotNull(w);
ErrLogDialog errDialog = getDialogComponentProvider(w, ErrLogDialog.class);
assertNotNull(errDialog);
return errDialog;
}
private void reportException(final DockingErrorDisplay display, final DefaultErrorLogger logger,
final Throwable throwable) {
runSwing(new Runnable() {
@Override

View file

@ -1094,8 +1094,24 @@ public abstract class AbstractGenericTest extends AbstractGTest {
return ref.get();
}
public static void runSwing(Runnable runnable) {
runSwing(runnable, true);
/**
* Run the given code snippet on the Swing thread and wait for it to finish
* @param r the runnable code snippet
*/
public static void runSwing(Runnable r) {
runSwing(r, true);
}
/**
* 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) {
runSwing(r, false);
}
/**
@ -1103,7 +1119,7 @@ public abstract class AbstractGenericTest extends AbstractGTest {
* an exception
* @param runnable the runnable
* @param wait true signals to wait for the Swing operation to finish
* @throws Throwable any excption that is thrown on the Swing thread
* @throws Throwable any exception that is thrown on the Swing thread
*/
public static void runSwingWithExceptions(Runnable runnable, boolean wait) throws Throwable {

View file

@ -1,36 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.util.exception;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
public interface CausesImportant {
public static class Util {
public static String getMessages(Throwable exc) {
if (exc instanceof CausesImportant) {
StringBuilder result = new StringBuilder(exc.getMessage());
for (Throwable cause : MultipleCauses.Util.iterCauses(exc)) {
result.append(
StringUtils.join(Arrays.asList(cause.getMessage().split("\n")), "\n\t"));
}
return result.toString();
}
return exc.getMessage();
}
}
}

View file

@ -1,30 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.util.exception;
public interface HasConsoleText {
public String getConsoleText();
public static class Util {
public static String get(Throwable exc) {
if (exc instanceof HasConsoleText) {
return ((HasConsoleText) exc).getConsoleText();
}
return null;
}
}
}

View file

@ -89,7 +89,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
protected DBHandle dbHandle;
private AddressMap addrMap;
private ErrorHandler errHandler;
private ErrorHandler errHandler = new DbErrorHandler();
private DataTypeConflictHandler currentHandler;
private CategoryDB root;
@ -168,12 +168,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
*/
protected DataTypeManagerDB() {
this.lock = new Lock("DataTypeManagerDB");
errHandler = new ErrorHandler() {
@Override
public void dbError(IOException e) {
Msg.showError(this, null, "IO ERROR", e.getMessage(), e);
}
};
try {
dbHandle = new DBHandle();
int id = startTransaction("");
@ -213,13 +208,6 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
") for read-only Datatype Archive: " + packedDBfile.getAbsolutePath());
}
errHandler = new ErrorHandler() {
@Override
public void dbError(IOException e) {
Msg.showError(this, null, "IO ERROR", e.getMessage(), e);
}
};
// Open packed database archive
boolean openSuccess = false;
PackedDatabase pdb = null;
@ -4089,6 +4077,20 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
}
}
private class DbErrorHandler implements ErrorHandler {
@Override
public void dbError(IOException e) {
String message = e.getMessage();
if (e instanceof ClosedException) {
message = "Data type archive is closed: " + getName();
}
Msg.showError(this, null, "IO ERROR", message, e);
}
}
}
/**

View file

@ -225,33 +225,6 @@ public class Msg {
}
}
/**
* Used to display a warning message to the user with a pop-up GUI dialog.
* Also records the message to the logging system.
*
* @param originator
* a Logger instance, "this", or YourClass.class
* @param parent
* a parent component used to center the dialog (or null if you
* don't have one)
* @param title
* the title of the pop-up dialog (main subject of message)
* @param message
* the details of the message
* @param throwable
* the Throwable that describes the cause of the warning
*/
public static void showWarn(Object originator, Component parent, String title, Object message,
Throwable throwable) {
if (SystemUtilities.isInHeadlessMode()) {
Msg.warn(originator, message, throwable);
}
else {
errorDisplay.displayWarningMessage(errorLogger, originator, parent, title, message,
throwable);
}
}
/**
* Used to display an error message with no available Throwable to the user
* via the console (no GUI). Also records the message to the logging system.

View file

@ -499,14 +499,31 @@ public class ReflectionUtilities {
* @return the string
*/
public static String stackTraceToString(Throwable t) {
StringBuffer sb = new StringBuffer();
return stackTraceToString(t.getMessage(), t);
}
/**
* Turns the given {@link Throwable} into a String version of its
* {@link Throwable#printStackTrace()} method.
*
* @param message the preferred message to use. If null, the throwable message will be used
* @param t the throwable
* @return the string
*/
public static String stackTraceToString(String message, Throwable t) {
StringBuilder sb = new StringBuilder();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
String msg = t.getMessage();
if (msg != null) {
ps.println(msg);
if (message != null) {
ps.println(message);
}
else {
String throwableMessage = t.getMessage();
if (throwableMessage != null) {
ps.println(throwableMessage);
}
}
t.printStackTrace(ps);

View file

@ -55,8 +55,8 @@ public class IntroScreenShots extends GhidraScreenShotGenerator {
@Test
public void testErr_Dialog() {
runSwing(() -> {
ErrLogDialog dialog = ErrLogDialog.createLogMessageDialog("Unexpected Error",
"Oops, this is really bad!", "");
ErrLogDialog dialog = ErrLogDialog.createExceptionDialog("Unexpected Error",
"Oops, this is really bad!", new Throwable());
DockingWindowManager.showDialog(null, dialog);
}, false);
waitForSwing();

View file

@ -25,6 +25,7 @@ import javax.swing.tree.TreePath;
import org.junit.*;
import docking.AbstractErrDialog;
import docking.ActionContext;
import docking.action.DockingActionIf;
import docking.widgets.MultiLineLabel;
@ -102,7 +103,7 @@ public class SetLanguageTest extends AbstractGhidraHeadedIntegrationTest {
@Test
public void testActionEnablement() throws Exception {
assertTrue(setLanguageAction.isEnabled());
assertTrue(!setLanguageAction.isEnabledForContext(createProjectDataContext(xyzFolderNode)));
assertFalse(setLanguageAction.isEnabledForContext(createProjectDataContext(xyzFolderNode)));
assertTrue(setLanguageAction.isEnabledForContext(createProjectDataContext(notepadNode)));
}
@ -110,7 +111,7 @@ public class SetLanguageTest extends AbstractGhidraHeadedIntegrationTest {
return addrFactory.getAddress(address);
}
private void startSetLanguage(final LanguageID languageID, final CompilerSpecID compilerSpecID,
private void startSetLanguage(LanguageID languageID, CompilerSpecID compilerSpecID,
boolean isFailureCase) throws Exception {
if (languageID == null) {
throw new RuntimeException("languageID == null not allowed");
@ -135,9 +136,9 @@ public class SetLanguageTest extends AbstractGhidraHeadedIntegrationTest {
pressButtonByText(confirmDlg, "Ok");
final SetLanguageDialog dlg = waitForDialogComponent(SetLanguageDialog.class);
SetLanguageDialog dlg = waitForDialogComponent(SetLanguageDialog.class);
assertNotNull(dlg);
final NewLanguagePanel languagePanel =
NewLanguagePanel languagePanel =
(NewLanguagePanel) getInstanceField("selectLangPanel", dlg);
assertNotNull(languagePanel);
@ -167,16 +168,16 @@ public class SetLanguageTest extends AbstractGhidraHeadedIntegrationTest {
private ActionContext createProjectDataContext(GTreeNode node) {
TreePath[] selectionPaths = { node.getTreePath() };
List<DomainFile> fileList = new ArrayList<>();
List<DomainFolder> folderList = new ArrayList<>();
if (node instanceof DomainFileNode) {
fileList.add(((DomainFileNode) node).getDomainFile());
}
else {
folderList.add(((DomainFolderNode)node).getDomainFolder());
folderList.add(((DomainFolderNode) node).getDomainFolder());
}
return new FrontEndProjectTreeContext(null, null, selectionPaths, folderList, fileList,
(DataTree) node.getTree(), true);
}
@ -208,13 +209,9 @@ public class SetLanguageTest extends AbstractGhidraHeadedIntegrationTest {
startSetLanguage(new LanguageID("8051:BE:16:default"), new CompilerSpecID("default"), true);
final OptionDialog errDlg = waitForDialogComponent(OptionDialog.class);
assertNotNull(errDlg);
MultiLineLabel msgLabel = findComponent(errDlg, MultiLineLabel.class);
assertNotNull(msgLabel);
assertTrue(msgLabel.getLabel().indexOf("Language translation not supported") >= 0);
pressButtonByText(errDlg, "OK");
AbstractErrDialog d = waitForErrorDialog();
assertTrue(d.getMessage().contains("Language translation not supported"));
close(d);
closeAllWindows();
}

View file

@ -25,6 +25,7 @@ import javax.swing.*;
import org.junit.*;
import org.junit.experimental.categories.Category;
import docking.AbstractErrDialog;
import docking.action.DockingActionIf;
import docking.widgets.OptionDialog;
import docking.wizard.WizardManager;
@ -300,10 +301,9 @@ public class ProjectInfoDialogTest extends AbstractGhidraHeadedIntegrationTest {
pressButtonByText(opt, "Update");
waitForTasks();
opt = waitForDialogComponent(OptionDialog.class);
assertNotNull(opt);
assertEquals("Failed to Update Shared Project Info", opt.getTitle());
opt.close();
AbstractErrDialog errorDialog = waitForErrorDialog();
assertEquals("Failed to Update Shared Project Info", errorDialog.getTitle());
close(errorDialog);
}
private void checkProjectInfo(String expectedRepName) {

View file

@ -24,9 +24,9 @@ import javax.swing.*;
import org.junit.Assert;
import org.junit.Test;
import docking.AbstractErrDialog;
import docking.ActionContext;
import docking.action.DockingActionIf;
import docking.widgets.MultiLineLabel;
import docking.widgets.OptionDialog;
import docking.widgets.table.GTable;
import docking.widgets.tree.GTreeNode;
@ -146,15 +146,15 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
GTreeNode nodeC = getNode(PROGRAM_C);
selectNodes(nodeA, nodeC);
final DockingActionIf action = getAction("Add to Version Control");
DockingActionIf action = getAction("Add to Version Control");
SwingUtilities.invokeLater(
() -> action.actionPerformed(getDomainFileActionContext(nodeA, nodeC)));
waitForSwing();
VersionControlDialog dialog = waitForDialogComponent(VersionControlDialog.class);
assertNotNull(dialog);
final JTextArea textArea = findComponent(dialog, JTextArea.class);
JTextArea textArea = findComponent(dialog, JTextArea.class);
assertNotNull(textArea);
final JCheckBox cb = findComponent(dialog, JCheckBox.class);
JCheckBox cb = findComponent(dialog, JCheckBox.class);
assertNotNull(cb);
runSwing(() -> {
textArea.setText("This is a test");
@ -176,11 +176,11 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
@Test
public void testCheckOut() throws Exception {
// add program to version control
final GTreeNode node = getNode(PROGRAM_A);
GTreeNode node = getNode(PROGRAM_A);
addToVersionControl(node, false);
selectNode(node);
final DockingActionIf action = getAction("CheckOut");
DockingActionIf action = getAction("CheckOut");
SwingUtilities.invokeLater(() -> action.actionPerformed(getDomainFileActionContext(node)));
waitForSwing();
waitForTasks();
@ -204,11 +204,11 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
@Test
public void testCheckIn() throws Exception {
final GTreeNode node = getNode(PROGRAM_A);
GTreeNode node = getNode(PROGRAM_A);
addToVersionControl(node, false);
selectNode(node);
final DockingActionIf action = getAction("CheckOut");
DockingActionIf action = getAction("CheckOut");
runSwing(() -> action.actionPerformed(getDomainFileActionContext(node)), false);
waitForSwing();
waitForTasks();
@ -227,14 +227,15 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
program.save(null, TaskMonitor.DUMMY);
}
program.release(this);
final DockingActionIf checkInAction = getAction("CheckIn");
DockingActionIf checkInAction = getAction("CheckIn");
runSwing(() -> checkInAction.actionPerformed(getDomainFileActionContext(node)), false);
waitForSwing();
VersionControlDialog dialog = waitForDialogComponent(VersionControlDialog.class);
assertNotNull(dialog);
final JTextArea textArea = findComponent(dialog, JTextArea.class);
JTextArea textArea = findComponent(dialog, JTextArea.class);
assertNotNull(textArea);
final JCheckBox cb = findComponent(dialog, JCheckBox.class);
JCheckBox cb = findComponent(dialog, JCheckBox.class);
assertNotNull(cb);
runSwing(() -> {
textArea.setText("This is a test");
@ -253,10 +254,10 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
setErrorGUIEnabled(true);// expect an error dialog
// create 3 versions of the program
doCreateVersions();
final GTreeNode node = getNode(PROGRAM_A);
GTreeNode node = getNode(PROGRAM_A);
selectNode(node);
final DockingActionIf historyAction = getAction("Show History");
DockingActionIf historyAction = getAction("Show History");
runSwing(() -> historyAction.actionPerformed(getDomainFileActionContext(node)));
VersionHistoryDialog dialog = waitForDialogComponent(VersionHistoryDialog.class);
@ -267,14 +268,9 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
performAction(deleteAction, false);
// cannot delete a file that is checked out
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
MultiLineLabel label = findComponent(d.getComponent(), MultiLineLabel.class);
assertNotNull(label);
assertEquals("File version has one or more checkouts.", label.getLabel());
runSwing(() -> d.close());
AbstractErrDialog d = waitForErrorDialog();
assertEquals("File version has one or more checkouts.", d.getMessage());
close(d);
}
@Test
@ -283,10 +279,10 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
setErrorGUIEnabled(true);// expect an error dialog
doCreateVersions();
final GTreeNode node = getNode(PROGRAM_A);
GTreeNode node = getNode(PROGRAM_A);
selectNode(node);
final DockingActionIf historyAction = getAction("Show History");
DockingActionIf historyAction = getAction("Show History");
runSwing(() -> historyAction.actionPerformed(getDomainFileActionContext(node)));
VersionHistoryDialog dialog = waitForDialogComponent(VersionHistoryDialog.class);
@ -297,17 +293,10 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
performAction(deleteAction, false);
// can delete only the first or last version of the file
OptionDialog d = waitForDialogComponent(OptionDialog.class);
assertNotNull(d);
MultiLineLabel label = findComponent(d.getComponent(), MultiLineLabel.class);
assertNotNull(label);
assertEquals("Only first and last version may be deleted.", label.getLabel());
runSwing(() -> {
d.close();
dialog.close();
});
AbstractErrDialog d = waitForErrorDialog();
assertEquals("Only first and last version may be deleted.", d.getMessage());
close(d);
close(dialog);
}
@Test
@ -341,7 +330,7 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
assertEquals(rowCount - 1, table.getRowCount());
runSwing(() -> dialog.close());
close(dialog);
}
@Test
@ -371,7 +360,7 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
FindCheckoutsDialog dialog = waitForDialogComponent(FindCheckoutsDialog.class);
assertNotNull(dialog);
final GTable table = findComponent(dialog.getComponent(), GTable.class);
GTable table = findComponent(dialog.getComponent(), GTable.class);
assertNotNull(table);
waitForBusyTable(table);