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>")) { if (message != null && message.toLowerCase().startsWith("<html>")) {
JEditorPane editorPane = new JEditorPane(); JEditorPane editorPane = new JEditorPane();
editorPane.setEditorKit(new HTMLEditorKit()); editorPane.setEditorKit(new HTMLEditorKit());
editorPane.setName("MESSAGE-COMPONENT"); editorPane.setName(MESSAGE_COMPONENT_NAME);
editorPane.setText(message); editorPane.setText(message);
editorPane.setBackground(new GLabel().getBackground()); editorPane.setBackground(new GLabel().getBackground());

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -15,7 +15,7 @@
*/ */
package ghidra.app.plugin.core.string; package ghidra.app.plugin.core.string;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -83,7 +83,7 @@ public class StringTableProviderTest extends AbstractGhidraHeadedIntegrationTest
CodeViewerProvider cbProvider = cb.getProvider(); CodeViewerProvider cbProvider = cb.getProvider();
SwingUtilities.invokeLater( SwingUtilities.invokeLater(
() -> searchAction.actionPerformed(cbProvider.getActionContext(null))); () -> searchAction.actionPerformed(cbProvider.getActionContext(null)));
waitForPostedSwingRunnables(); waitForSwing();
return getDialogComponent(SearchStringDialog.class); return getDialogComponent(SearchStringDialog.class);
} }
@ -317,7 +317,7 @@ public class StringTableProviderTest extends AbstractGhidraHeadedIntegrationTest
selectRows(address); // string abcefg is here selectRows(address); // string abcefg is here
performAction(makeStringAction, false); performAction(makeStringAction, false);
waitForPostedSwingRunnables(); waitForSwing();
OptionDialog dialogProvider = getDialogComponent(OptionDialog.class); OptionDialog dialogProvider = getDialogComponent(OptionDialog.class);
assertNotNull(dialogProvider); assertNotNull(dialogProvider);
@ -435,13 +435,9 @@ public class StringTableProviderTest extends AbstractGhidraHeadedIntegrationTest
} }
private void createDataAt(Address addr) throws Exception { private void createDataAt(Address addr) throws Exception {
int id = program.startTransaction("test"); tx(program, () -> {
try {
program.getListing().createData(addr, new ByteDataType()); program.getListing().createData(addr, new ByteDataType());
} });
finally {
program.endTransaction(id, true);
}
} }
private void setCheckbox(final JCheckBox checkbox, final boolean selected) { 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, private void toggleDefinedStateButtons(final boolean defined, final boolean undefined,
final boolean partial, final boolean conflicting) { final boolean partial, final boolean conflicting) {
runSwing(() -> { runSwing(() -> {

View file

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

View file

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

View file

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

View file

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

View file

@ -105,7 +105,7 @@ public final class CryptoKeyFactory {
} }
} }
catch (Exception e) { 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); "Unable to process crypto keys files.", e);
} }
} }

View file

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

View file

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

View file

@ -24,7 +24,6 @@ import javax.swing.*;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import docking.widgets.MultiLineLabel;
import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.AddressSet; import ghidra.program.model.address.AddressSet;
@ -353,9 +352,6 @@ public class DiffGetTest extends DiffTestAdapter {
assertNull(fp2.getTopLevelAncestor()); assertNull(fp2.getTopLevelAncestor());
Window win = waitForWindow("Can't Open Selected Program"); 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"); pressButton(win, "OK");
win = waitForWindow("Select Other Program"); win = waitForWindow("Select Other Program");
assertNotNull(win); assertNotNull(win);

View file

@ -147,9 +147,6 @@ public class DualProgramTest extends DiffTestAdapter {
waitForTasks(); waitForTasks();
win = waitForWindow("Can't Open Selected Program"); 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"); pressButton(win, "OK");
win = waitForWindow("Select Other Program"); win = waitForWindow("Select Other Program");

View file

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

View file

@ -17,7 +17,6 @@ package docking;
import java.awt.Component; import java.awt.Component;
import java.awt.Window; import java.awt.Window;
import java.io.*;
import docking.widgets.OkDialog; import docking.widgets.OkDialog;
import docking.widgets.OptionDialog; import docking.widgets.OptionDialog;
@ -26,7 +25,16 @@ import ghidra.util.exception.MultipleCauses;
public class DockingErrorDisplay implements ErrorDisplay { 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(); ConsoleErrorDisplay consoleDisplay = new ConsoleErrorDisplay();
@ -52,8 +60,8 @@ public class DockingErrorDisplay implements ErrorDisplay {
private void displayMessage(MessageType messageType, ErrorLogger errorLogger, Object originator, private void displayMessage(MessageType messageType, ErrorLogger errorLogger, Object originator,
Component parent, String title, Object message, Throwable throwable) { 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 messageString = message != null ? message.toString() : null;
String rawMessage = HTMLUtilities.fromHTML(messageString); String rawMessage = HTMLUtilities.fromHTML(messageString);
switch (messageType) { switch (messageType) {
@ -75,7 +83,7 @@ public class DockingErrorDisplay implements ErrorDisplay {
break; break;
} }
showDialog(title, message, throwable, dialogType, messageString, getWindow(parent)); showDialog(title, throwable, dialogType, messageString, getWindow(parent));
} }
private Component getWindow(Component component) { private Component getWindow(Component component) {
@ -85,33 +93,45 @@ public class DockingErrorDisplay implements ErrorDisplay {
return component; 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) { 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, if (dialogType == OptionDialog.ERROR_MESSAGE) {
int dialogType, String messageString, Component parent) { // Note: all calls to manipulate the error dialog must be on the Swing thread to
DialogComponentProvider dialog = null; // guarantee thread visibility to our state variables
if (throwable != null) { Swing.runIfSwingOrRunLater(
dialog = createErrorDialog(title, message, throwable, messageString); () -> showDialogOnSwing(title, throwable, dialogType, messageString, parent));
} }
else { 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, private void showDialogOnSwing(String title, Throwable throwable,
final Throwable throwable, String messageString) { 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)) { if (containsMultipleCauses(throwable)) {
return new ErrLogExpandableDialog(title, messageString, throwable); return new ErrLogExpandableDialog(title, messageString, throwable);
} }
return ErrLogDialog.createExceptionDialog(title, messageString, return ErrLogDialog.createExceptionDialog(title, messageString, throwable);
buildStackTrace(throwable, message == null ? throwable.getMessage() : messageString));
} }
private boolean containsMultipleCauses(Throwable throwable) { private boolean containsMultipleCauses(Throwable throwable) {
@ -125,34 +145,4 @@ public class DockingErrorDisplay implements ErrorDisplay {
return containsMultipleCauses(throwable.getCause()); 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.awt.event.ComponentEvent;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.*; import javax.swing.*;
import docking.widgets.ScrollableTextArea; import docking.widgets.ScrollableTextArea;
import docking.widgets.label.GHtmlLabel; import docking.widgets.label.GHtmlLabel;
import docking.widgets.label.GIconLabel; import docking.widgets.label.GIconLabel;
import docking.widgets.table.*;
import generic.json.Json;
import generic.util.WindowUtilities; import generic.util.WindowUtilities;
import ghidra.docking.settings.Settings;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.framework.plugintool.ServiceProviderStub;
import ghidra.util.HTMLUtilities; 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 TEXT_COLUMNS = 80;
private static final int ERROR_BUFFER_SIZE = 1024;
private static final String SEND = "Log Error..."; private static final String SEND = "Log Error...";
private static final String DETAIL = "Details >>>"; private static final String DETAIL = "Details >>>";
@ -46,32 +61,30 @@ public class ErrLogDialog extends DialogComponentProvider {
/** tracks 'details panel' open state across invocations */ /** tracks 'details panel' open state across invocations */
private static boolean isShowingDetails = false; private static boolean isShowingDetails = false;
private int errorId = 0;
// state-dependent gui members // state-dependent gui members
private ErrorDetailsPanel detailsPanel; private ErrorDetailsSplitPane detailsPane;
private JButton detailsButton; private JButton detailsButton;
private JButton sendButton; private JButton sendButton;
private JPanel mainPanel; private JPanel mainPanel;
private static ErrorReporter errorReporter; private static ErrorReporter errorReporter;
public static ErrLogDialog createExceptionDialog(String title, String message, String details) { private List<ErrorEntry> errors = new ArrayList<>();
return new ErrLogDialog(title, message, details, true);
public static ErrLogDialog createExceptionDialog(String title, String message, Throwable t) {
return new ErrLogDialog(title, message, t);
} }
public static ErrLogDialog createLogMessageDialog(String title, String message, private ErrLogDialog(String title, String message, Throwable throwable) {
String details) { super(title != null ? title : "Error");
return new ErrLogDialog(title, message, details, false);
} 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); setRememberSize(false);
setRememberLocation(false); setRememberLocation(false);
buildMainPanel(message, addUsefulReportingInfo(details), isException); buildMainPanel(message);
} }
private String addUsefulReportingInfo(String details) { private String addUsefulReportingInfo(String details) {
@ -127,13 +140,21 @@ public class ErrLogDialog extends DialogComponentProvider {
return errorReporter; return errorReporter;
} }
private void buildMainPanel(String message, String details, boolean isException) { private void buildMainPanel(String message) {
JPanel introPanel = new JPanel(new BorderLayout(10, 10)); JPanel introPanel = new JPanel(new BorderLayout(10, 10));
introPanel.add( introPanel.add(
new GIconLabel(UIManager.getIcon("OptionPane.errorIcon"), SwingConstants.RIGHT), new GIconLabel(UIManager.getIcon("OptionPane.errorIcon"), SwingConstants.RIGHT),
BorderLayout.WEST); 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 = new JPanel(new BorderLayout(10, 20));
mainPanel.add(introPanel, BorderLayout.NORTH); mainPanel.add(introPanel, BorderLayout.NORTH);
@ -141,21 +162,15 @@ public class ErrLogDialog extends DialogComponentProvider {
sendButton = new JButton(SEND); sendButton = new JButton(SEND);
sendButton.addActionListener(e -> sendDetails()); sendButton.addActionListener(e -> sendDetails());
detailsPanel = new ErrorDetailsPanel();
detailsButton = new JButton(isShowingDetails ? CLOSE : DETAIL); detailsButton = new JButton(isShowingDetails ? CLOSE : DETAIL);
detailsButton.addActionListener(e -> { detailsButton.addActionListener(e -> {
String label = detailsButton.getText(); String label = detailsButton.getText();
showDetails(label.equals(DETAIL)); showDetails(label.equals(DETAIL));
}); });
if (isException) { detailsPane = new ErrorDetailsSplitPane();
detailsPanel.setExceptionMessage(details);
}
else {
detailsPanel.setLogMessage(details);
}
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)); buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
if (errorReporter != null) { if (errorReporter != null) {
buttonPanel.add(sendButton); buttonPanel.add(sendButton);
@ -163,16 +178,16 @@ public class ErrLogDialog extends DialogComponentProvider {
buttonPanel.add(detailsButton); buttonPanel.add(detailsButton);
introPanel.add(buttonPanel, BorderLayout.EAST); introPanel.add(buttonPanel, BorderLayout.EAST);
mainPanel.add(detailsPanel, BorderLayout.CENTER); mainPanel.add(detailsPane, BorderLayout.CENTER);
addWorkPanel(mainPanel); addWorkPanel(mainPanel);
addOKButton(); addOKButton();
setDefaultButton(okButton);
// show the details panel if it was showing previously // show the details panel if it was showing previously
detailsPanel.setVisible(isShowingDetails); detailsPane.setVisible(isShowingDetails);
detailsPane.selectFirstError();
// setHelpLocation(new HelpLocation(HelpTopics.INTRO, "Err"));
} }
@Override @Override
@ -185,82 +200,69 @@ public class ErrLogDialog extends DialogComponentProvider {
cancelCallback(); cancelCallback();
} }
/**
* Send error details from dialog.
*/
private void sendDetails() { private void sendDetails() {
String details = detailsPanel.getDetails(); String details = detailsPane.getDetails();
String title = getTitle(); String title = getTitle();
close(); close();
errorReporter.report(rootPanel, title, details); 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) { private void showDetails(boolean visible) {
isShowingDetails = visible; isShowingDetails = visible;
String label = (visible ? CLOSE : DETAIL); String label = (visible ? CLOSE : DETAIL);
detailsButton.setText(label); detailsButton.setText(label);
detailsPanel.setVisible(visible); detailsPane.setVisible(visible);
repack(); // need to re-pack so the detailsPanel can be hidden correctly repack(); // need to re-pack so the detailsPanel can be hidden correctly
} }
// custom "pack" so the detailsPanel can be shown/hidden correctly
@Override @Override
protected void repack() { public String getMessage() {
return detailsPane.getMessage();
// 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);
} }
@Override @Override
protected void dialogShown() { protected void dialogShown() {
// TODO test that the parent DockingDialog code handles this....
WindowUtilities.ensureOnScreen(getDialog()); WindowUtilities.ensureOnScreen(getDialog());
Swing.runLater(() -> okButton.requestFocusInWindow());
} }
/** @Override
* scrolled text panel used to display the error message details; void addException(String message, Throwable t) {
* each time an error message is "added", appends the contents to
* the internal StringBuffer. int n = errors.size();
*/ if (n > MAX_EXCEPTIONS) {
private class ErrorDetailsPanel extends JPanel { return;
private ScrollableTextArea textDetails; }
private StringBuffer errorDetailsBuffer;
private Dimension closedSize; 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 Dimension openedSize;
private ErrorDetailsPanel() { ErrorDetailsSplitPane() {
super(new BorderLayout(0, 0)); super(VERTICAL_SPLIT);
errorDetailsBuffer = new StringBuffer(ERROR_BUFFER_SIZE); setResizeWeight(TOP_PREFERRED_RESIZE_WEIGHT);
textDetails = new ScrollableTextArea(TEXT_ROWS, TEXT_COLUMNS);
textDetails.setEditable(false);
add(textDetails, BorderLayout.CENTER);
validate();
textDetails.scrollToBottom();
// set the initial preferred size of this panel detailsPanel = new ErrorDetailsPanel();
// when "closed" tablePanel = new ErrorDetailsTablePanel();
Rectangle bounds = getBounds();
closedSize = new Dimension(bounds.width, 0); setTopComponent(detailsPanel);
setBottomComponent(tablePanel);
addComponentListener(new ComponentAdapter() { addComponentListener(new ComponentAdapter() {
@Override @Override
@ -269,51 +271,283 @@ public class ErrLogDialog extends DialogComponentProvider {
return; return;
} }
Rectangle localBounds = getBounds(); Rectangle localBounds = getBounds();
if (detailsButton.getText().equals(DETAIL)) { if (!detailsButton.getText().equals(DETAIL)) {
closedSize.width = localBounds.width;
}
else {
openedSize = new Dimension(localBounds.width, localBounds.height); 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 @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
if (detailsButton.getText().equals(DETAIL)) { if (detailsButton.getText().equals(DETAIL)) {
return closedSize; return superSize;
} }
if (openedSize == null) { if (openedSize == null) {
return super.getPreferredSize(); return superSize;
} }
return openedSize; return openedSize;
} }
}
private class ErrorDetailsTablePanel extends JPanel {
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();
}
}
/** /**
* resets the current error buffer to the contents of msg * 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 void setLogMessage(String msg) { private class ErrorDetailsPanel extends JPanel {
errorDetailsBuffer = new StringBuffer(msg);
textDetails.setText(msg);
// scroll to bottom so user is viewing the last message 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(); textDetails.scrollToBottom();
} }
private void setExceptionMessage(String msg) { void setError(ErrorEntry e) {
errorDetailsBuffer = new StringBuffer(msg); error = e;
textDetails.setText(msg); 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 // scroll to the top the see the pertinent part of the exception
textDetails.scrollToTop(); textDetails.scrollToTop();
} }
private final String getDetails() { String getDetails() {
return errorDetailsBuffer.toString(); 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.*;
import docking.widgets.tree.support.GTreeDragNDropHandler; import docking.widgets.tree.support.GTreeDragNDropHandler;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.*; import ghidra.util.exception.MultipleCauses;
import ghidra.util.html.HTMLElement; import ghidra.util.html.HTMLElement;
import resources.ResourceManager; import resources.ResourceManager;
import util.CollectionUtils; 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_REPORT = ResourceManager.loadImage("images/report.png");
public static ImageIcon IMG_EXCEPTION = ResourceManager.loadImage("images/exception.png"); public static ImageIcon IMG_EXCEPTION = ResourceManager.loadImage("images/exception.png");
public static ImageIcon IMG_FRAME_ELEMENT = public static ImageIcon IMG_FRAME_ELEMENT =
@ -53,113 +53,21 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
private static boolean showingDetails = false; private static boolean showingDetails = false;
protected ReportRootNode root; 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 */ /** This spacer addresses the optical impression that the message panel changes size when showing details */
protected Component horizontalSpacer; protected Component horizontalSpacer;
protected JButton detailButton; protected JButton detailButton;
protected JButton sendButton; protected JButton sendButton;
protected boolean hasConsole = false;
protected JPopupMenu popup; protected JPopupMenu popup;
protected static class ExcTreeTransferHandler extends TransferHandler protected ErrLogExpandableDialog(String title, String msg, Throwable throwable) {
implements GTreeDragNDropHandler { 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(); popup = new JPopupMenu();
JMenuItem menuCopy = new JMenuItem("Copy"); JMenuItem menuCopy = new JMenuItem("Copy");
menuCopy.setActionCommand((String) TransferHandler.getCopyAction().getValue(Action.NAME)); menuCopy.setActionCommand((String) TransferHandler.getCopyAction().getValue(Action.NAME));
@ -173,13 +81,12 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
msgPanel.setLayout(new BorderLayout(16, 16)); msgPanel.setLayout(new BorderLayout(16, 16));
msgPanel.setBorder(new EmptyBorder(16, 16, 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 @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
// when rendering HTML the label can expand larger than the screen; // rendering HTML the label can expand larger than the screen; keep it reasonable
// keep it reasonable
Dimension size = super.getPreferredSize(); Dimension size = super.getPreferredSize();
size.width = 500; size.width = 300;
return size; return size;
} }
}; };
@ -206,7 +113,7 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
msgPanel.add(buttonBox, BorderLayout.EAST); msgPanel.add(buttonBox, BorderLayout.EAST);
horizontalSpacer = Box.createVerticalStrut(10); horizontalSpacer = Box.createVerticalStrut(10);
horizontalSpacer.setVisible(showingDetails | hasConsole); horizontalSpacer.setVisible(showingDetails);
msgPanel.add(horizontalSpacer, BorderLayout.SOUTH); msgPanel.add(horizontalSpacer, BorderLayout.SOUTH);
} }
workPanel.add(msgPanel, BorderLayout.NORTH); workPanel.add(msgPanel, BorderLayout.NORTH);
@ -214,29 +121,8 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
Box workBox = Box.createVerticalBox(); Box workBox = Box.createVerticalBox();
{ {
if (hasConsole) { root = new ReportRootNode(getTitle(), CollectionUtils.asSet(throwable));
JTextArea consoleText = new JTextArea(console); tree = new GTree(root) {
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) {
@Override @Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
@ -249,19 +135,19 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
for (GTreeNode node : CollectionUtils.asIterable(root.iterator(true))) { for (GTreeNode node : CollectionUtils.asIterable(root.iterator(true))) {
if (node instanceof ReportExceptionNode) { if (node instanceof ReportExceptionNode) {
excTree.expandTree(node); tree.expandTree(node);
} }
} }
excTree.setSelectedNode(root.getChild(0)); tree.setSelectedNode(root.getChild(0));
excTree.setVisible(showingDetails); tree.setVisible(showingDetails);
ExcTreeTransferHandler handler = new ExcTreeTransferHandler(root); ExcTreeTransferHandler handler = new ExcTreeTransferHandler(root);
excTree.setDragNDropHandler(handler); tree.setDragNDropHandler(handler);
excTree.setTransferHandler(handler); tree.setTransferHandler(handler);
ActionMap map = excTree.getActionMap(); ActionMap map = tree.getActionMap();
map.put(TransferHandler.getCopyAction().getValue(Action.NAME), map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
TransferHandler.getCopyAction()); TransferHandler.getCopyAction());
excTree.addMouseListener(new MouseAdapter() { tree.addMouseListener(new MouseAdapter() {
@Override @Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
maybeShowPopup(e); maybeShowPopup(e);
@ -279,22 +165,19 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
} }
}); });
workBox.add(excTree); workBox.add(tree);
} }
workPanel.add(workBox, BorderLayout.CENTER); workPanel.add(workBox, BorderLayout.CENTER);
repack(); repack();
addWorkPanel(workPanel); addWorkPanel(workPanel);
if (hasDismiss) {
addDismissButton(); addDismissButton();
} }
}
private String getHTML(String msg, Collection<Throwable> report) { private String getHTML(String msg, Collection<Throwable> report) {
// //
// TODO
// Usage question: The content herein will be escaped unless you call addHTMLContenet(). // Usage question: The content herein will be escaped unless you call addHTMLContenet().
// Further, clients can provide messages that contain HTML. Is there a // Further, clients can provide messages that contain HTML. Is there a
// use case where we want to show escaped HTML content? // use case where we want to show escaped HTML content?
@ -332,14 +215,6 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
String htmlTMsg = addBR(tMsg); String htmlTMsg = addBR(tMsg);
body.addElement("p").addHTMLContent(htmlTMsg); 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(); return html.toString();
} }
@ -357,15 +232,15 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
return t.getClass().getSimpleName(); return t.getClass().getSimpleName();
} }
void detailCallback() { private void detailCallback() {
showingDetails = !showingDetails; showingDetails = !showingDetails;
excTree.setVisible(showingDetails); tree.setVisible(showingDetails);
horizontalSpacer.setVisible(showingDetails | hasConsole); horizontalSpacer.setVisible(showingDetails);
detailButton.setText(showingDetails ? CLOSE : DETAIL); detailButton.setText(showingDetails ? CLOSE : DETAIL);
repack(); repack();
} }
void sendCallback() { private void sendCallback() {
String details = root.collectReportText(null, 0).trim(); String details = root.collectReportText(null, 0).trim();
String title = getTitle(); String title = getTitle();
close(); close();
@ -379,6 +254,29 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
return dim; 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 { static interface NodeWithText {
public String getReportText(); public String getReportText();
@ -528,9 +426,6 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
@Override @Override
public String getReportText() { public String getReportText() {
if (exc instanceof HasConsoleText) {
return getName() + "\n" + HasConsoleText.Util.get(exc);
}
return getName(); return getName();
} }
@ -661,6 +556,87 @@ public class ErrLogExpandableDialog extends DialogComponentProvider {
return false; 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 { class TransferActionListener implements ActionListener, PropertyChangeListener {

View file

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

View file

@ -99,7 +99,7 @@ import ghidra.util.exception.AssertException;
* @see OptionDialogBuilder * @see OptionDialogBuilder
*/ */
public class OptionDialog extends DialogComponentProvider { 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. */ /** Used for error messages. */
public static final int ERROR_MESSAGE = 0; public static final int ERROR_MESSAGE = 0;
/** Used for information messages. */ /** Used for information messages. */

View file

@ -111,6 +111,7 @@ public class ScrollableTextArea extends JScrollPane {
/** /**
* Returns the number of lines current set in the text area * Returns the number of lines current set in the text area
* @return the count
*/ */
public int getLineCount() { public int getLineCount() {
return textArea.getLineCount(); return textArea.getLineCount();
@ -118,6 +119,7 @@ public class ScrollableTextArea extends JScrollPane {
/** /**
* Returns the tab size set in the text area * Returns the tab size set in the text area
* @return the size
*/ */
public int getTabSize() { public int getTabSize() {
return textArea.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) * Returns the total area height of the text area (row height * line count)
* @return the height
*/ */
public int getTextAreaHeight() { public int getTextAreaHeight() {
return (textArea.getAreaHeight()); return (textArea.getAreaHeight());
@ -132,6 +135,7 @@ public class ScrollableTextArea extends JScrollPane {
/** /**
* Returns the visible height of the text area * Returns the visible height of the text area
* @return the height
*/ */
public int getTextVisibleHeight() { public int getTextVisibleHeight() {
return textArea.getVisibleHeight(); return textArea.getVisibleHeight();
@ -200,6 +204,7 @@ public class ScrollableTextArea extends JScrollPane {
/** /**
* Returns the text contained within the text area * Returns the text contained within the text area
* @return the text
*/ */
public String getText() { public String getText() {
return textArea.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(); DockingErrorDisplay display = new DockingErrorDisplay();
DefaultErrorLogger logger = new DefaultErrorLogger(); DefaultErrorLogger logger = new DefaultErrorLogger();
Exception exception = new Exception("My test exception"); Exception exception = new Exception("My test exception");
doDisplay(display, logger, exception); reportException(display, logger, exception);
assertErrLogDialog(); assertErrLogDialog();
} }
@ -46,11 +46,29 @@ public class DockingErrorDisplayTest extends AbstractDockingTest {
DefaultErrorLogger logger = new DefaultErrorLogger(); DefaultErrorLogger logger = new DefaultErrorLogger();
Exception nestedException = new Exception("My nested test exception"); Exception nestedException = new Exception("My nested test exception");
Exception exception = new Exception("My test exception", nestedException); Exception exception = new Exception("My test exception", nestedException);
doDisplay(display, logger, exception); reportException(display, logger, exception);
assertErrLogDialog(); 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 @Test
public void testMultipleCausesErrorDisplay() { public void testMultipleCausesErrorDisplay() {
DockingErrorDisplay display = new DockingErrorDisplay(); DockingErrorDisplay display = new DockingErrorDisplay();
@ -58,43 +76,51 @@ public class DockingErrorDisplayTest extends AbstractDockingTest {
Throwable firstCause = new Exception("My test exception - first cause"); Throwable firstCause = new Exception("My test exception - first cause");
MultipleCauses exception = new MultipleCauses(Collections.singletonList(firstCause)); 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() { private void assertExceptionCount(AbstractErrDialog errDialog, int n) {
Window w = waitForWindow(TEST_TITLE, 2000);
assertNotNull(w);
final ErrLogExpandableDialog errDialog = int actual = errDialog.getExceptionCount();
assertEquals(n, actual);
}
private ErrLogExpandableDialog assertErrLogExpandableDialog() {
Window w = waitForWindow(TEST_TITLE);
ErrLogExpandableDialog errDialog =
getDialogComponentProvider(w, ErrLogExpandableDialog.class); getDialogComponentProvider(w, ErrLogExpandableDialog.class);
assertNotNull(errDialog); assertNotNull(errDialog);
return errDialog;
runSwing(new Runnable() {
@Override
public void run() {
errDialog.close();
}
});
} }
private void assertErrLogDialog() { private void assertErrLogDialog() {
Window w = waitForWindow(TEST_TITLE, 2000); Window w = waitForWindow(TEST_TITLE);
assertNotNull(w); assertNotNull(w);
final ErrLogDialog errDialog = getDialogComponentProvider(w, ErrLogDialog.class); ErrLogDialog errDialog = getDialogComponentProvider(w, ErrLogDialog.class);
assertNotNull(errDialog); assertNotNull(errDialog);
close(errDialog);
runSwing(new Runnable() {
@Override
public void run() {
errDialog.close();
}
});
} }
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) { final Throwable throwable) {
runSwing(new Runnable() { runSwing(new Runnable() {
@Override @Override

View file

@ -1094,8 +1094,24 @@ public abstract class AbstractGenericTest extends AbstractGTest {
return ref.get(); 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 * an exception
* @param runnable the runnable * @param runnable the runnable
* @param wait true signals to wait for the Swing operation to finish * @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 { 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; protected DBHandle dbHandle;
private AddressMap addrMap; private AddressMap addrMap;
private ErrorHandler errHandler; private ErrorHandler errHandler = new DbErrorHandler();
private DataTypeConflictHandler currentHandler; private DataTypeConflictHandler currentHandler;
private CategoryDB root; private CategoryDB root;
@ -168,12 +168,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
*/ */
protected DataTypeManagerDB() { protected DataTypeManagerDB() {
this.lock = new Lock("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 { try {
dbHandle = new DBHandle(); dbHandle = new DBHandle();
int id = startTransaction(""); int id = startTransaction("");
@ -213,13 +208,6 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
") for read-only Datatype Archive: " + packedDBfile.getAbsolutePath()); ") 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 // Open packed database archive
boolean openSuccess = false; boolean openSuccess = false;
PackedDatabase pdb = null; 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 * 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. * 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 * @return the string
*/ */
public static String stackTraceToString(Throwable t) { 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(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos); PrintStream ps = new PrintStream(baos);
String msg = t.getMessage(); if (message != null) {
if (msg != null) { ps.println(message);
ps.println(msg); }
else {
String throwableMessage = t.getMessage();
if (throwableMessage != null) {
ps.println(throwableMessage);
}
} }
t.printStackTrace(ps); t.printStackTrace(ps);

View file

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

View file

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

View file

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

View file

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